Re: [MPlayer-dev-eng] RFC on libspe2 detection
Rasmus Rohde wrote:
Hopefully we will at some point see some additions to mplayer, which will make use of libspe2 (the SPE library for the Cell BE).
Great!
I already have a beta vo_fbdevps3.c, which makes use of the SPEs for scaling and color conversion. Also it uses some features found specifically in the PS3 framebuffer.
Nice, would be hard split the scaling&color conversion and have it also in swscale? (I know it won't be _that_ easy)
The attached patch adds detection for libspe2 to the configure script.
I sent a patch to provide a pkg-config to libspe2 recently (while starting something on ffmpeg)
Is this the way to go our should we instead detect the target is e.g. PS3 and then add libspe2 as a needed library?
I like this way better. lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero
I already have a beta vo_fbdevps3.c, which makes use of the SPEs for scaling and color conversion. Also it uses some features found specifically in the PS3 framebuffer. Nice, would be hard split the scaling&color conversion and have it also in swscale? (I know it won't be _that_ easy) Color conversion and scaling is already done as two different jobs. I'm not sure how difficult it would be to put in swscale, but it seems to me that it normally works on slices of the picture. For the SPUs to be effective it is much easier to work on entire frames. In this way we can kick off a SPU doing e.g. scaling and color conversion on an entire frame, while we work on the next frame.
Is this the way to go our should we instead detect the target is e.g. PS3 and then add libspe2 as a needed library? I like this way better. Okie - I've put together an updated patch which also detects if we have spu-gcc and ppu-embedspu available. Furthermore I've included my current version of vo_fbdevps3.c together with the SPU code that does color conversion and scaling.
At the moment color conversion (yuv to rgb) is done before scaling, which will probably change at a later stage. This will also fix the problems that is present now with color conversion only working on widths that are multiples of 32. However if anybody should be interested the patch can be found here: http://www.duff.dk/ps3/vo_fbdevps3-patch-1 Since it is rather large I will not post it to the mailing list.
On Tue, May 15, 2007 at 10:52:17PM +0200, Rasmus Rohde wrote:
However if anybody should be interested the patch can be found here: http://www.duff.dk/ps3/vo_fbdevps3-patch-1
You should clean up the licensing. vo_fbdevps3_scaler.c has a license template, not a license, vo_fbdevps3.c has nothing at all. The stuff in the spe subdir claims to be BSD-licensed. There is no such thing as "the" BSD license. There are several variants, some of which are problematic, i.e. GPL-incompatible. Diego
However if anybody should be interested the patch can be found here: http://www.duff.dk/ps3/vo_fbdevps3-patch-1 You should clean up the licensing. The stuff in the spe subdir claims to be BSD-licensed. There is no such thing as "the" BSD license. There are several variants, some of which are problematic, i.e. GPL-incompatible. I did not write the yuv2rgb and therefore I am not able to change the license on that one. However I decided instead to write my own, which solves that problem.
I've cooked together a new patch if anybody should be interested http://www.duff.dk/ps3/vo_fbdevps3-patch-2 The files are now without licenses at all, which I think should be ok.
Rasmus Rohde wrote:
The files are now without licenses at all, which I think should be ok.
Not really, just take the mplayer license as template (even better ffmpeg lgpl if you allow us to move some of the code into ffmpeg swscale), a file without license has full copyright to the original author to my knowledge... lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero
The files are now without licenses at all, which I think should be ok. Not really, just take the mplayer license as template (even better ffmpeg lgpl if you allow us to move some of the code into ffmpeg swscale), a file without license has full copyright to the original author to my knowledge... Argh - I hate licenses :)
Feel free to change the license to whatever ffmpeg uses. ffmpeg lgpl is fine with me.
On Thu, May 17, 2007 at 09:12:15AM +0200, Rasmus Rohde wrote:
The files are now without licenses at all, which I think should be ok. Not really, just take the mplayer license as template (even better ffmpeg lgpl if you allow us to move some of the code into ffmpeg swscale), a file without license has full copyright to the original author to my knowledge... Argh - I hate licenses :)
It's the sensible default. If you don't give explicit permission to redistribute and reuse then it's assumed not to exist. Think about it, how would you feel if your code showed up in a proprietary product of company X tomorrow without any compensation or even credit?
Feel free to change the license to whatever ffmpeg uses. ffmpeg lgpl is fine with me.
This is not really something we should be doing for you. Just put in the correct license header or at least a statement to that effect. Diego
On Thu, May 17, 2007 at 12:01:09AM +0200, Rasmus Rohde wrote:
However if anybody should be interested the patch can be found here: http://www.duff.dk/ps3/vo_fbdevps3-patch-1 You should clean up the licensing. The stuff in the spe subdir claims to be BSD-licensed. There is no such thing as "the" BSD license. There are several variants, some of which are problematic, i.e. GPL-incompatible. I did not write the yuv2rgb and therefore I am not able to change the license on that one.
You could ask the author(s) to clarify/change it.
However I decided instead to write my own, which solves that problem.
I've cooked together a new patch if anybody should be interested http://www.duff.dk/ps3/vo_fbdevps3-patch-2
The files are now without licenses at all, which I think should be ok.
No, it's not OK, on the contrary. Code should have a clear license statement. A missing license statement is not clear at all. Diego
Rasmus Rohde wrote: [patch] here some nits: - avoid unnecessary casts - why are you favoring the usage of the external program instead of the embedded one? shouldn't be the opposite? (you fallback to the external program only if you hadn't embedded the spu code?) - shouldn't first set up the handler and then, if everything is fine, spawn the new thread? - you could factorize some constants - please have your code formatted to 97 col bound otherwise is a bit harder to read. lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero
On Thu, May 17, 2007 at 09:42:58AM +0200, Luca Barbato wrote:
- please have your code formatted to 97 col bound otherwise is a bit harder to read.
Luca means no more than 79/80 characters per line. Diego
- avoid unnecessary casts I've walked through the code and removed what I could find of unnecessary casts.
- why are you favoring the usage of the external program instead of the embedded one? shouldn't be the opposite? (you fallback to the external program only if you hadn't embedded the spu code?) If you have written super ultimate Vista scaler ++ 2.0 and want to use that instead, you can do it without recompiling mplayer.
It's extremely nice when you are just testing since compiling some spu code is pretty fast whereas compiling mplayer takes a bit longer.
- shouldn't first set up the handler and then, if everything is fine, spawn the new thread? Sounds reasonable. Fix it.
- you could factorize some constants I probably could. That will have to wait.
- please have your code formatted to 97 col bound otherwise is a bit harder to read. I've reduced line width to 80 all the places I found it makes sense. The macro stuff in the SPE code is ugly from the beginning and trying to fit it into 80 does not help much. I could perhaps move it to the top of the file and avoid a lot of indentation.
Rasmus Rohde wrote:
- avoid unnecessary casts I've walked through the code and removed what I could find of unnecessary casts.
I think there are still some...
- why are you favoring the usage of the external program instead of the embedded one? shouldn't be the opposite? (you fallback to the external program only if you hadn't embedded the spu code?) If you have written super ultimate Vista scaler ++ 2.0 and want to use that instead, you can do it without recompiling mplayer.
A consisten way should be the one used by the vo_opengl, but could wait for later.
- you could factorize some constants I probably could. That will have to wait.
I'll help =) lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero
Rasmus Rohde wrote: [fixes from my previous batch] Some new: asm/ps3fb.h may or may not exist, please check for it's presence (both system headers and kernel headers) and fall back to local definitions if not possible. try to avoid warnings due missing includes. Hopefully I'll write something about spu/cell toolchain support soonish. lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero
Luca Barbato wrote:
Hopefully I'll write something about spu/cell toolchain support soonish.
Here the initial kludge. What's missing: - make the vo behave like a normal vo configure/build wise - make the vo independent to the spu scaler/converter - make the vo behave like the gl one What should be done: - move the scaler/converter to swscaler on a second time (pending swscaler clenaup) lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero Index: libvo/spe/vo_fbdevps3_yuv2rgb.c =================================================================== --- libvo/spe/vo_fbdevps3_yuv2rgb.c (revision 0) +++ libvo/spe/vo_fbdevps3_yuv2rgb.c (revision 0) @@ -0,0 +1,354 @@ +/* + * YUV 2 RGB converter + * Copyright (c) 2007 Rasmus Rohde <rohde@duff.dk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This progam 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <spu_mfcio.h> +#include <spu_intrinsics.h> +#include <malloc.h> + +#include "yuv_datastructs.h" + +int main(unsigned long long spe_id, unsigned long long program_data_ea, + unsigned long long env) { + img_args pd __attribute__((aligned(16))); + unsigned long long Yin; + unsigned long long Uin; + unsigned long long Vin; + unsigned long long Output; + + vector unsigned char *YtempA1, *YtempB1, *YtempA2, *YtempB2; + vector unsigned char *UtempA, *UtempB; + vector unsigned char *VtempA, *VtempB; + vector unsigned char *OutA1, *OutA2, *OutB1, *OutB2; + + int i, x, y; + int width, height, widthdiv16; + + int mbox_val; + int tag_id_input_yA = 1; + int tag_id_input_yB = 2; + int tag_id_input_uvA = 4; + int tag_id_input_uvB = 8; + int tag_id_output = 16; + + //Initiate copy + mfc_get(&pd, program_data_ea, sizeof(pd), tag_id_input_yA, 0, 0); + //Wait for completion + mfc_write_tag_mask(1<<tag_id_input_yA); + mfc_read_tag_status_any(); + + width = pd.width; + widthdiv16 = width / 16; + height = pd.height; + + YtempA1 = (vector unsigned char *)memalign(16, width*2); + YtempA2 = YtempA1 + width / sizeof(*YtempA1); + UtempA = (vector unsigned char *)memalign(16, width); + VtempA = (vector unsigned char *)memalign(16, width); + + YtempB1 = (vector unsigned char *)memalign(16, width*2); + YtempB2 = YtempB1 + width / sizeof(*YtempB1); + UtempB = (vector unsigned char *)memalign(16, width); + VtempB = (vector unsigned char *)memalign(16, width); + + OutA1 = (vector unsigned char *)memalign(16, width*4*2); + OutA2 = OutA1 + width * 4 / sizeof(*OutA1); + + OutB1 = (vector unsigned char *)memalign(16, width*4*2); + OutB2 = OutB1 + width * 4 / sizeof(*OutB1); + + do { + // Tell PPU we are ready for the next frame + spu_writech(SPU_WrOutIntrMbox, 0); + + mbox_val = spu_read_in_mbox(); + + if(mbox_val < 0) + break; + + Yin = pd.Ystart[mbox_val]; + Uin = pd.Ustart[mbox_val]; + Vin = pd.Vstart[mbox_val]; + Output = pd.Output[mbox_val]; + + mfc_get(YtempA1, Yin, width*2, tag_id_input_yA, 0, 0); + mfc_get(UtempA, Uin, width, tag_id_input_uvA, 0, 0); + mfc_get(VtempA, Vin, width, tag_id_input_uvA, 0, 0); + + Yin += width*2; + Uin += width; + Vin += width; + + vector float mulV1 = spu_splats(1.402f); + vector float mulV2 = spu_splats(-0.71414f); + vector float mulU1 = spu_splats(-0.34414f); + vector float mulU2 = spu_splats(1.772f); + vector float minus128f = spu_splats(-128.0f); + vector unsigned int max = spu_splats((unsigned int)255); + unsigned int uv_offset1, uv_offset2; + for(y=0; y<height/4; y++) { + unsigned long pixel_offset1 = 0; + unsigned long pixel_offset2 = 0; + mfc_get(YtempB1, Yin, width*2, tag_id_input_yB, 0, 0); + Yin += width*2; + + if((y & 1) == 0) { + mfc_get(UtempB, Uin, width, tag_id_input_uvB, + 0, 0); + mfc_get(VtempB, Vin, width, tag_id_input_uvB, + 0, 0); + Uin += width; + Vin += width; + + mfc_write_tag_mask(1<<tag_id_input_uvA); + mfc_read_tag_status_any(); + uv_offset1 = 0; + } else { + mfc_write_tag_mask(1<<tag_id_input_yA); + mfc_read_tag_status_any(); + } + +#define extractYUV(UVOFF, YOFF, YBUF1, YBUF2) \ + vector unsigned char Ydata1 = YBUF1[YOFF]; \ + vector unsigned char Ydata2 = YBUF2[YOFF]; \ + vector unsigned char Y1 = spu_shuffle(Ydata1, Ydata1, ((vector unsigned char){0x80,0x80,0x80,0,0x80,0x80,0x80,1,0x80,0x80,0x80,2,0x80,0x80,0x80,3})); \ + vector unsigned char Y2 = spu_shuffle(Ydata1, Ydata1, ((vector unsigned char){0x80,0x80,0x80,4,0x80,0x80,0x80,5,0x80,0x80,0x80,6,0x80,0x80,0x80,7})); \ + vector unsigned char Y3 = spu_shuffle(Ydata1, Ydata1, ((vector unsigned char){0x80,0x80,0x80,8,0x80,0x80,0x80,9,0x80,0x80,0x80,10,0x80,0x80,0x80,11})); \ + vector unsigned char Y4 = spu_shuffle(Ydata1, Ydata1, ((vector unsigned char){0x80,0x80,0x80,12,0x80,0x80,0x80,13,0x80,0x80,0x80,14,0x80,0x80,0x80,15})); \ + vector float Y1F = spu_convtf((vector unsigned int)Y1, 0); \ + vector float Y2F = spu_convtf((vector unsigned int)Y2, 0); \ + vector float Y3F = spu_convtf((vector unsigned int)Y3, 0); \ + vector float Y4F = spu_convtf((vector unsigned int)Y4, 0); \ + \ + vector unsigned char U1 = spu_shuffle(Udata, Udata, ((vector unsigned char){0x80,0x80,0x80,0+UVOFF,0x80,0x80,0x80,0+UVOFF,0x80,0x80,0x80,1+UVOFF,0x80,0x80,0x80,1+UVOFF})); \ + vector unsigned char U2 = spu_shuffle(Udata, Udata, ((vector unsigned char){0x80,0x80,0x80,2+UVOFF,0x80,0x80,0x80,2+UVOFF,0x80,0x80,0x80,3+UVOFF,0x80,0x80,0x80,3+UVOFF})); \ + vector unsigned char U3 = spu_shuffle(Udata, Udata, ((vector unsigned char){0x80,0x80,0x80,4+UVOFF,0x80,0x80,0x80,4+UVOFF,0x80,0x80,0x80,5+UVOFF,0x80,0x80,0x80,5+UVOFF})); \ + vector unsigned char U4 = spu_shuffle(Udata, Udata, ((vector unsigned char){0x80,0x80,0x80,6+UVOFF,0x80,0x80,0x80,6+UVOFF,0x80,0x80,0x80,7+UVOFF,0x80,0x80,0x80,7+UVOFF})); \ + vector float U1F = spu_convtf((vector unsigned int)U1, 0); \ + vector float U2F = spu_convtf((vector unsigned int)U2, 0); \ + vector float U3F = spu_convtf((vector unsigned int)U3, 0); \ + vector float U4F = spu_convtf((vector unsigned int)U4, 0); \ + U1F = spu_add(U1F, minus128f); \ + U2F = spu_add(U2F, minus128f); \ + U3F = spu_add(U3F, minus128f); \ + U4F = spu_add(U4F, minus128f); \ + \ + vector unsigned char V1 = spu_shuffle(Vdata, Vdata, ((vector unsigned char){0x80,0x80,0x80,0+UVOFF,0x80,0x80,0x80,0+UVOFF,0x80,0x80,0x80,1+UVOFF,0x80,0x80,0x80,1+UVOFF})); \ + vector unsigned char V2 = spu_shuffle(Vdata, Vdata, ((vector unsigned char){0x80,0x80,0x80,2+UVOFF,0x80,0x80,0x80,2+UVOFF,0x80,0x80,0x80,3+UVOFF,0x80,0x80,0x80,3+UVOFF})); \ + vector unsigned char V3 = spu_shuffle(Vdata, Vdata, ((vector unsigned char){0x80,0x80,0x80,4+UVOFF,0x80,0x80,0x80,4+UVOFF,0x80,0x80,0x80,5+UVOFF,0x80,0x80,0x80,5+UVOFF})); \ + vector unsigned char V4 = spu_shuffle(Vdata, Vdata, ((vector unsigned char){0x80,0x80,0x80,6+UVOFF,0x80,0x80,0x80,6+UVOFF,0x80,0x80,0x80,7+UVOFF,0x80,0x80,0x80,7+UVOFF})); \ + vector float V1F = spu_convtf((vector unsigned int)V1, 0); \ + vector float V2F = spu_convtf((vector unsigned int)V2, 0); \ + vector float V3F = spu_convtf((vector unsigned int)V3, 0); \ + vector float V4F = spu_convtf((vector unsigned int)V4, 0); \ + V1F = spu_add(V1F, minus128f); \ + V2F = spu_add(V2F, minus128f); \ + V3F = spu_add(V3F, minus128f); \ + V4F = spu_add(V4F, minus128f); + +#define convert4pixels(YF, UF, VF, OUT, PIXOFF) { \ + vector float G = spu_madd(UF, mulU1, YF); \ + vector float R = spu_madd(VF, mulV1, YF); \ + vector float B = spu_madd(UF, mulU2, YF); \ + G = spu_madd(VF, mulV2, G); \ + \ + vector unsigned int Ri = spu_convtu(R, 0); \ + vector unsigned int Bi = spu_convtu(B, 0); \ + vector unsigned int Gi = spu_convtu(G, 0); \ + \ + vector unsigned int T1 = spu_cmpgt(Ri, 255); \ + vector unsigned int T2 = spu_cmpgt(Bi, 255); \ + vector unsigned int T3 = spu_cmpgt(Gi, 255); \ + \ + Ri = spu_sel(Ri, max, T1); \ + Bi = spu_sel(Bi, max, T2); \ + Gi = spu_sel(Gi, max, T3); \ + \ + vector unsigned char pixel = spu_shuffle((vector unsigned char)Ri, (vector unsigned char)Bi, ((vector unsigned char){0x80, 3, 0x80, 19, 0x80, 7, 0x80, 23, 0x80, 11, 0x80, 27, 0x80, 15, 0x80, 31})); \ + OUT[PIXOFF++] = spu_shuffle(pixel, (vector unsigned char)Gi, ((vector unsigned char){0, 1, 19, 3, 4, 5, 23, 7, 8, 9, 27, 11, 12, 13, 31, 15})); \ + } + +#define extractYline2() \ + Y1 = spu_shuffle(Ydata2, Ydata2, ((vector unsigned char){0x80,0x80,0x80,0,0x80,0x80,0x80,1,0x80,0x80,0x80,2,0x80,0x80,0x80,3})); \ + Y2 = spu_shuffle(Ydata2, Ydata2, ((vector unsigned char){0x80,0x80,0x80,4,0x80,0x80,0x80,5,0x80,0x80,0x80,6,0x80,0x80,0x80,7})); \ + Y3 = spu_shuffle(Ydata2, Ydata2, ((vector unsigned char){0x80,0x80,0x80,8,0x80,0x80,0x80,9,0x80,0x80,0x80,10,0x80,0x80,0x80,11})); \ + Y4 = spu_shuffle(Ydata2, Ydata2, ((vector unsigned char){0x80,0x80,0x80,12,0x80,0x80,0x80,13,0x80,0x80,0x80,14,0x80,0x80,0x80,15})); \ + Y1F = spu_convtf((vector unsigned int)Y1, 0); \ + Y2F = spu_convtf((vector unsigned int)Y2, 0); \ + Y3F = spu_convtf((vector unsigned int)Y3, 0); \ + Y4F = spu_convtf((vector unsigned int)Y4, 0); + + // Do first 2 lines + for(x=0; x<widthdiv16; x++) { + vector unsigned char Udata = + UtempA[uv_offset1/2]; + vector unsigned char Vdata = + VtempA[uv_offset1/2]; + + // Do the 16 pixels - 2 lines + if((uv_offset1 & 1) == 0) { + extractYUV(0, x, YtempA1, YtempA2); + // Convert pixels for the first line + convert4pixels(Y1F, U1F, V1F, OutA1, + pixel_offset1); + convert4pixels(Y2F, U2F, V2F, OutA1, + pixel_offset1); + convert4pixels(Y3F, U3F, V3F, OutA1, + pixel_offset1); + convert4pixels(Y4F, U4F, V4F, OutA1, + pixel_offset1); + + extractYline2(); + + // Convert pixels for the second line + convert4pixels(Y1F, U1F, V1F, OutA2, + pixel_offset2); + convert4pixels(Y2F, U2F, V2F, OutA2, + pixel_offset2); + convert4pixels(Y3F, U3F, V3F, OutA2, + pixel_offset2); + convert4pixels(Y4F, U4F, V4F, OutA2, + pixel_offset2); + } else { + extractYUV(8, x, YtempA1, YtempA2); + // Convert pixels for the first line + convert4pixels(Y1F, U1F, V1F, OutA1, + pixel_offset1); + convert4pixels(Y2F, U2F, V2F, OutA1, + pixel_offset1); + convert4pixels(Y3F, U3F, V3F, OutA1, + pixel_offset1); + convert4pixels(Y4F, U4F, V4F, OutA1, + pixel_offset1); + + extractYline2(); + + // Convert pixels for the second line + convert4pixels(Y1F, U1F, V1F, OutA2, + pixel_offset2); + convert4pixels(Y2F, U2F, V2F, OutA2, + pixel_offset2); + convert4pixels(Y3F, U3F, V3F, OutA2, + pixel_offset2); + convert4pixels(Y4F, U4F, V4F, OutA2, + pixel_offset2); + } + + uv_offset1++; + } + mfc_put(OutA1, Output, width * 4 * 2, tag_id_output, + 0, 0); + Output += width * 4 * 2; + + // Do next 2 lines + pixel_offset1 = 0; + pixel_offset2 = 0; + + if(y+1 < height/4) { + // Only get next line if we are not done yet + mfc_get(YtempA1, Yin, width*2, tag_id_input_yA, + 0, 0); + Yin += width*2; + + if((y & 1) == 1) { + mfc_get(UtempA, Uin, width, + tag_id_input_uvA, 0, 0); + mfc_get(VtempA, Vin, width, + tag_id_input_uvA, 0, 0); + Uin += width; + Vin += width; + + mfc_write_tag_mask(1<<tag_id_input_yB); + mfc_read_tag_status_any(); + } else { + mfc_write_tag_mask(1<<tag_id_input_uvB); + mfc_read_tag_status_any(); + uv_offset2 = 0; + } + } + + // Do first 2 lines + for(x=0; x<widthdiv16; x++) { + vector unsigned char Udata = + UtempB[uv_offset2/2]; + vector unsigned char Vdata = + VtempB[uv_offset2/2]; + + // Do the 16 pixels - 2 lines + if((uv_offset2 & 1) == 0) { + extractYUV(0, x, YtempB1, YtempB2); + // Convert pixels for the first line + convert4pixels(Y1F, U1F, V1F, OutB1, + pixel_offset1); + convert4pixels(Y2F, U2F, V2F, OutB1, + pixel_offset1); + convert4pixels(Y3F, U3F, V3F, OutB1, + pixel_offset1); + convert4pixels(Y4F, U4F, V4F, OutB1, + pixel_offset1); + + extractYline2(); + + // Convert pixels for the second line + convert4pixels(Y1F, U1F, V1F, OutB2, + pixel_offset2); + convert4pixels(Y2F, U2F, V2F, OutB2, + pixel_offset2); + convert4pixels(Y3F, U3F, V3F, OutB2, + pixel_offset2); + convert4pixels(Y4F, U4F, V4F, OutB2, + pixel_offset2); + } else { + extractYUV(8, x, YtempB1, YtempB2); + // Convert pixels for the first line + convert4pixels(Y1F, U1F, V1F, OutB1, + pixel_offset1); + convert4pixels(Y2F, U2F, V2F, OutB1, + pixel_offset1); + convert4pixels(Y3F, U3F, V3F, OutB1, + pixel_offset1); + convert4pixels(Y4F, U4F, V4F, OutB1, + pixel_offset1); + + extractYline2(); + + // Convert pixels for the second line + convert4pixels(Y1F, U1F, V1F, OutB2, + pixel_offset2); + convert4pixels(Y2F, U2F, V2F, OutB2, + pixel_offset2); + convert4pixels(Y3F, U3F, V3F, OutB2, + pixel_offset2); + convert4pixels(Y4F, U4F, V4F, OutB2, + pixel_offset2); + } + + uv_offset2++; + } + + mfc_put(OutB1, Output, width * 4 * 2, + tag_id_output, 0, 0); + Output += width * 4 * 2; + } + + // Wait for last transfer to finish + mfc_write_tag_mask(1<<tag_id_output); + mfc_read_tag_status_any(); + } while(1); + + return 0; +} Index: libvo/spe/yuv_datastructs.h =================================================================== --- libvo/spe/yuv_datastructs.h (revision 0) +++ libvo/spe/yuv_datastructs.h (revision 0) @@ -0,0 +1,33 @@ +/* + * YUV 2 RGB converter + * Copyright (c) 2007 Rasmus Rohde <rohde@duff.dk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This progam 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __YUV_DATASTRUCTS_H +#define __YUV_DATASTRUCTS_H + +typedef struct { + int width; + int height; + unsigned long long Ystart[2]; + unsigned long long Ustart[2]; + unsigned long long Vstart[2]; + unsigned long long Output[2]; +} __attribute__((aligned(16))) img_args; + +#endif + Index: libvo/spe/vo_fbdevps3_scaler.c =================================================================== --- libvo/spe/vo_fbdevps3_scaler.c (revision 0) +++ libvo/spe/vo_fbdevps3_scaler.c (revision 0) @@ -0,0 +1,372 @@ +/* + * RGB bilinear scaler + * Copyright (c) 2007 Rasmus Rohde <rohde@duff.dk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This progam 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <spu_mfcio.h> +#include <spu_intrinsics.h> +#include <malloc.h> + +typedef struct { + unsigned long long in[2]; + unsigned long long out[2]; + + unsigned int in_width; // Must be a multiple of 4 + float scale; + unsigned int out_height; + unsigned int out_width_total; // Must be a multiple of 4 + unsigned int out_width_overscan; // Must be a multiple of 4 +} __attribute__((aligned(16))) spe_data; + +static inline void pixels_to_svector(vector unsigned char *pixels, + vector unsigned short *dst); + +/* + Bilinear scaler. Input must be 24-bit RGB where unsigned char in[0] = 0, + in[1] = red, in[2] = green, in[3] = blue. + + Output will be in the same format. + + To quit the SPE thread write a number <= 0 in its mailbox. + To scale to out[0] from in[0] write 1 in its mailbox and write 2 + to use out[1] from in[1] + + A zero will be written to the interrupt mailbox when a new frame is ready + to be received. + + Compile with -funroll-loops -O4 for best performance. + */ +int main(unsigned long long spe_id, unsigned long long program_data_ea, + unsigned long long env) { + vector unsigned char *temp_output_vec; + vector unsigned short *in_line_temp; + vector unsigned short *hscaled_line; + vector unsigned char *in_line_dma_buf; + vector unsigned short *hfilter, *hfilterPos; + unsigned short *vfilter, *vfilterPos; + + spe_data pd __attribute__((aligned(16))); + + unsigned int yc __attribute__((aligned(16))); + unsigned int xc __attribute__((aligned(16))); + unsigned int out_height __attribute__((aligned(16))); + unsigned int out_width_total __attribute__((aligned(16))); + unsigned int out_width __attribute__((aligned(16))); + float scale __attribute__((aligned(16))); + + unsigned int width8x __attribute__((aligned(16))); + + vector unsigned char extract_pix = {0x80, 0x80, 0x80, 0x80, 0x80, 5, + 0x80, 21, 0x80, 9, 0x80, 25, 0x80, + 13, 0x80, 29}; + + int tag_id_input = 1; + int tag_id_output = 2; + + //Initiate copy + mfc_get(&pd, program_data_ea, sizeof(pd), tag_id_input, 0, 0); + //Wait for completion + mfc_write_tag_mask(1<<tag_id_input); + mfc_read_tag_status_any(); + + width8x = pd.in_width * 8; + out_height = pd.out_height; + scale = pd.scale; + out_width = (pd.out_width_total - pd.out_width_overscan); + out_width_total = pd.out_width_total << 2; + + temp_output_vec = (vector unsigned char *)memalign(16, out_width*4); + in_line_temp = (vector unsigned short *) + memalign(16,pd.in_width*sizeof(*in_line_temp)); + hscaled_line = (vector unsigned short *) + memalign(16, out_width*sizeof(*hscaled_line)); + in_line_dma_buf = (vector unsigned char *)memalign(16, pd.in_width*4*2); + + // Construct the filters needed + vfilterPos = (unsigned short *) + memalign(16, out_height*sizeof(*vfilterPos)); + vfilter = (unsigned short *)memalign(16, out_height*2*sizeof(*vfilter)); + hfilterPos = (vector unsigned short *) + memalign(16, out_width*sizeof(unsigned short)); + hfilter = (vector unsigned short *) + memalign(16, out_width*sizeof(unsigned short)*2); + + for(xc=0; xc<out_width; xc+=8) { + unsigned short tempPos[8] __attribute__((aligned(16))); + unsigned short temp[16] __attribute__((aligned(16))); + for(yc=0; yc<8; yc++) { + float pos = ((xc+yc)*scale); + int ipos = (int)pos; + int w = (int)((pos-ipos) * 65536.0f); + if(w == 0) + w = 1; + else if(w >= 65536) + w = 65535; + tempPos[yc] = ipos; + temp[yc*2] = 65536-w; + temp[yc*2+1] = w; + } + hfilterPos[xc/8] = *(vector unsigned short *)tempPos; + hfilter[xc/4] = *(vector unsigned short *)temp; + hfilter[xc/4+1] = *(vector unsigned short *)&temp[8]; + } + + for(yc=0; yc<out_height; yc++) { + float pos = (yc*scale); + int ipos = (int)pos; + int w = (int)((pos-ipos) * 65536.0f); + if(w == 0) + w = 1; + else if(w >= 65536) + w = 65535; + + vfilterPos[yc] = ipos; + vfilter[yc*2] = 65536-w; + vfilter[yc*2+1] = w; + } + + do { + int pixel_y, dma_data_ready; + int line_in_use_dma_buf = 0; + int hscaled_line_in_use = 0; + vector unsigned short *next_hscaled_line = hscaled_line; + vector unsigned char *next_in_line_dma_buf = in_line_dma_buf; + int last_transferred_line; + int last_converted_line; + int mbox_val; + unsigned long long in __attribute__((aligned(16))); + unsigned long long out __attribute__((aligned(16))); + unsigned long long in_temp; + vector unsigned short *hline1 = hscaled_line; + vector unsigned short *hline2 = hscaled_line+out_width/2; + + // Wait for completion from possible previous transfer + mfc_write_tag_mask(1<<tag_id_output); + mfc_read_tag_status_any(); + + // Tell PPU we are ready for the next frame + spu_writech(SPU_WrOutIntrMbox, 0); + + mbox_val = spu_read_in_mbox(); + + if(mbox_val <= 0) + break; + + in = pd.in[mbox_val - 1]; + out = pd.out[mbox_val - 1]; + + // No matter what we always need the first two lines + mfc_get(in_line_dma_buf, in, width8x, tag_id_input, 0, 0); + in_temp = in + width8x; + last_transferred_line = 1; + last_converted_line = -1; + dma_data_ready = 1; + pixel_y = 0; + for(yc=0; yc<out_height; yc++) { + if(pixel_y >= last_converted_line) { + int i; + // Ok - we need to do some work since we are + // missing the next lines. + // First make sure the dma transfer is done + if(dma_data_ready) { + mfc_write_tag_mask(1<<tag_id_input); + mfc_read_tag_status_any(); + dma_data_ready = 0; + } + + for(i=0; i<2; i++) { + vector unsigned short *t1 = in_line_temp; + // Convert the data to short + for(xc=0; xc<width8x / 64; xc++) { + pixels_to_svector(next_in_line_dma_buf, t1); + t1 += 8; + next_in_line_dma_buf += 2; + } + + // Do hscale of it + for(xc=0; xc<out_width/8; xc++) { + + vector unsigned short pos = hfilterPos[xc]; + vector unsigned short w1 = hfilter[xc*2]; + vector unsigned short w2 = hfilter[xc*2+1]; + +#define HSCALE_TWO_PIXELS(weight, offset) { \ + vector unsigned short pixel0 = in_line_temp[spu_extract(pos, 0+offset)]; \ + vector unsigned short w_pix0_e = spu_splats(spu_extract(weight, 0)); \ + vector unsigned short w_pix0_o = spu_splats(spu_extract(weight, 1)); \ + vector unsigned short pixel1 = in_line_temp[spu_extract(pos, 1+offset)]; \ + vector unsigned short w_pix1_e = spu_splats(spu_extract(weight, 2)); \ + vector unsigned short w_pix1_o = spu_splats(spu_extract(weight, 3)); \ + vector unsigned short pixel2 = in_line_temp[spu_extract(pos, 2+offset)]; \ + vector unsigned short w_pix2_e = spu_splats(spu_extract(weight, 4)); \ + vector unsigned short w_pix2_o = spu_splats(spu_extract(weight, 5)); \ + vector unsigned short pixel3 = in_line_temp[spu_extract(pos, 3+offset)]; \ + vector unsigned short w_pix3_e = spu_splats(spu_extract(weight, 6)); \ + vector unsigned short w_pix3_o = spu_splats(spu_extract(weight, 7)); \ + vector unsigned int res1 = spu_mule(pixel0, w_pix0_e); \ + vector unsigned int res2 = spu_mulo(pixel0, w_pix0_o); \ + vector unsigned int res3 = spu_mule(pixel1, w_pix1_e); \ + vector unsigned int res4 = spu_mulo(pixel1, w_pix1_o); \ + res1 = spu_add(res1, res2); \ + res3 = spu_add(res3, res4); \ + *next_hscaled_line = (vector unsigned short)spu_shuffle(res1, res3, extract_pix); \ + next_hscaled_line++; \ + res1 = spu_mule(pixel2, w_pix2_e); \ + res2 = spu_mulo(pixel2, w_pix2_o); \ + res3 = spu_mule(pixel3, w_pix3_e); \ + res4 = spu_mulo(pixel3, w_pix3_o); \ + res1 = spu_add(res1, res2); \ + res3 = spu_add(res3, res4); \ + *next_hscaled_line = spu_shuffle((vector unsigned short)res1, (vector unsigned short)res3, extract_pix); \ + next_hscaled_line++; \ + } + HSCALE_TWO_PIXELS(w1, 0); + HSCALE_TWO_PIXELS(w2, 4); + } + hscaled_line_in_use ^= 1; + if(hscaled_line_in_use == 0) { + next_hscaled_line = + hscaled_line; + } + + line_in_use_dma_buf ^= 1; + if(line_in_use_dma_buf == 0) { + next_in_line_dma_buf = + in_line_dma_buf; + } + + // Check if we need to convert 2 + // lines this time + if(pixel_y <= last_converted_line) { + break; + } + } + + if(i == 2) { + last_converted_line += 2; + } else { + vector unsigned short *temp; + /* Since we just swapped the line in + buffer around also swap the offset */ + temp = hline1; + hline1 = hline2; + hline2 = temp; + last_converted_line++; + } + } + + pixel_y = vfilterPos[yc+1]; + + if(pixel_y >= last_transferred_line && + yc+2 < out_height) { + // Start transfer of the next 2 lines + mfc_get(in_line_dma_buf, in_temp, width8x, + tag_id_input, 0, 0); + in_temp += width8x; + + if(pixel_y > last_transferred_line) { + // Make absolutely sure we get 2 + // conversions next time + last_converted_line = pixel_y - 1; + } + + last_transferred_line += 2; + dma_data_ready = 1; + } + + vector unsigned short w1 = spu_splats(vfilter[yc*2]); + vector unsigned short w2 = spu_splats(vfilter[yc*2+1]); + + for(xc=0; xc<out_width/2; xc+=2) { + vector unsigned char rtemp1, rtemp2; + static vector unsigned char out_pixel_perm1 = + {0,5,9,13,0,21,25,29,0,0,0,0,0,0,0,0}; + static vector unsigned char out_pixel_perm2 = + {0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23}; + + vector unsigned short pixel_l1 = hline1[xc]; + vector unsigned short pixel_l2 = hline2[xc]; + + vector unsigned int res1 = spu_mule(pixel_l1, + w1); + vector unsigned int res2 = spu_mulo(pixel_l1, + w1); + vector unsigned int res3 = spu_mule(pixel_l2, + w2); + vector unsigned int res4 = spu_mulo(pixel_l2, + w2); + + res1 = spu_add(res1, res3); + res2 = spu_add(res2, res4); + + pixel_l1 = hline1[xc+1]; + pixel_l2 = hline2[xc+1]; + + res3 = spu_mule(pixel_l1, w1); + res4 = spu_mulo(pixel_l1, w1); + + rtemp1 = (vector unsigned char) + spu_shuffle(res1, res2, out_pixel_perm1); + + res1 = spu_mule(pixel_l2, w2); + res2 = spu_mulo(pixel_l2, w2); + + res1 = spu_add(res1, res3); + res2 = spu_add(res2, res4); + + rtemp2 = (vector unsigned char) + spu_shuffle(res1, res2, out_pixel_perm1); + + temp_output_vec[xc/2] = + spu_shuffle(rtemp1, rtemp2, + out_pixel_perm2); + } + + mfc_put(temp_output_vec, out, + out_width << 2, tag_id_output, 0, 0); + + out += out_width_total; + } + } while(1); + + return 0; +} + +static inline void pixels_to_svector(vector unsigned char *pixels, vector unsigned short *dst) +{ + static vector unsigned char extract_pix1 = {16,16,16,16,16,1,16, + 5,16,2,16,6,16,3,16,7}; + static vector unsigned char extract_pix2 = {16,16,16,16,16,5,16,9, + 16,6,16,10,16,7,16,11}; + static vector unsigned char extract_pix3 = {16,16,16,16,16,9,16,13, + 16,10,16,14,16,11,16,15}; + static vector unsigned char extract_pix4 = {16,16,16,16,16,13,16,17, + 16,14,16,18,16,15,16,19}; + + static vector unsigned char zero_vec = + (vector unsigned char){0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + vector unsigned char t1 = pixels[0]; + vector unsigned char t2 = pixels[1]; + vector unsigned char t3 = pixels[2]; + dst[0] = (vector unsigned short)spu_shuffle(t1, zero_vec, extract_pix1); + dst[1] = (vector unsigned short)spu_shuffle(t1, zero_vec, extract_pix2); + dst[2] = (vector unsigned short)spu_shuffle(t1, zero_vec, extract_pix3); + dst[3] = (vector unsigned short)spu_shuffle(t1, t2, extract_pix4); + dst[4] = (vector unsigned short)spu_shuffle(t2, zero_vec, extract_pix1); + dst[5] = (vector unsigned short)spu_shuffle(t2, zero_vec, extract_pix2); + dst[6] = (vector unsigned short)spu_shuffle(t2, zero_vec, extract_pix3); + dst[7] = (vector unsigned short)spu_shuffle(t2, t3, extract_pix4); +} Index: libvo/spe/Makefile =================================================================== --- libvo/spe/Makefile (revision 0) +++ libvo/spe/Makefile (revision 0) @@ -0,0 +1,15 @@ +include ../../config.mak + +CC=${SPUCC} +CFLAGS=-funroll-loops -O4 -Wall + +all: vo_fbdevps3_yuv2rgb vo_fbdevps3_scaler + +vo_fbdevps3_yuv2rgb: vo_fbdevps3_yuv2rgb.o + $(CC) -o $@ $< + +vo_fbdevps3_scaler: vo_fbdevps3_scaler.o + $(CC) -o $@ $< + +clean: + rm -f *~ *.o vo_fbdevps3_yuv2rgb vo_fbdevps3_scaler Index: libvo/Makefile =================================================================== --- libvo/Makefile (revision 23402) +++ libvo/Makefile (working copy) @@ -13,6 +13,7 @@ $(VO_SRCS) \ SRCS_MPLAYER-$(VIDIX) += vosub_vidix.c +SRCS_MPLAYER-$(CONFIG_LIBSPE2) += vo_fbdevps3.c SRCS_COMMON = aclib.c \ osd.c \ @@ -20,8 +21,23 @@ SRCS_COMMON-$(BITMAP_FONT) += font_load.c SRCS_COMMON-$(FREETYPE) += font_load_ft.c +ifeq ($(CONFIG_SPU),yes) +OBJS_MPLAYER += vo_fbdevps3_scaler.o vo_fbdevps3_yuv2rgb.o +endif include ../mpcommon.mak +ifeq ($(CONFIG_SPU),yes) +SPUFLAGS=-O4 -funroll-loops +vo_fbdevps3_scaler.o: spe/vo_fbdevps3_scaler.c + $(SPUCC) $(SPUFLAGS) -o vo_fbdevps3_scaler $< + $(EMBEDSPU) vo_fbdevps3_scaler vo_fbdevps3_scaler $@ + +vo_fbdevps3_yuv2rgb.o: spe/vo_fbdevps3_yuv2rgb.c + $(SPUCC) $(SPUFLAGS) -o vo_fbdevps3_yuv2rgb $< + $(EMBEDSPU) vo_fbdevps3_yuv2rgb vo_fbdevps3_yuv2rgb $@ + +endif + %.o: %.m $(CC) $(CFLAGS) -c -o $@ $< Index: libvo/video_out.c =================================================================== --- libvo/video_out.c (revision 23402) +++ libvo/video_out.c (working copy) @@ -94,6 +94,9 @@ extern vo_functions_t video_out_caca; extern vo_functions_t video_out_mpegpes; extern vo_functions_t video_out_yuv4mpeg; +#if (HAVE_LIBSPE2) && (HAVE_SPUGCC) +extern vo_functions_t video_out_fbdevps3; +#endif #ifdef HAVE_DIRECTX extern vo_functions_t video_out_directx; #endif @@ -200,6 +203,9 @@ &video_out_fbdev, &video_out_fbdev2, #endif +#if (HAVE_LIBSPE2) && (HAVE_SPUGCC) + &video_out_fbdevps3, +#endif #ifdef HAVE_SVGALIB &video_out_svga, #endif Index: libvo/vo_fbdevps3.c =================================================================== --- libvo/vo_fbdevps3.c (revision 0) +++ libvo/vo_fbdevps3.c (revision 0) @@ -0,0 +1,725 @@ +/* + * PS3 specific framebuffer video output + * Copyright (c) 2007 Rasmus Rohde <rohde@duff.dk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This progam 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <errno.h> +#include <linux/fb.h> +#include <sys/kd.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <libspe2.h> +//#include <asm/ps3fb.h> + + +#include "video_out.h" +#include "video_out_internal.h" +#include "mp_msg.h" + +#include "spe/yuv_datastructs.h" + +// ugly yet simple workaround +#ifndef _PS3FB_H_ +#define _PS3FB_H_ + +/* ioctl */ +#define PS3FB_IOCTL_SETMODE _IOW('r', 1, int) /* set video mode */ +#define PS3FB_IOCTL_GETMODE _IOR('r', 2, int) /* get video mode */ +#define PS3FB_IOCTL_SCREENINFO _IOR('r', 3, int) /* get screen info */ +#define PS3FB_IOCTL_ON _IO('r', 4) /* use IOCTL_FSEL */ +#define PS3FB_IOCTL_OFF _IO('r', 5) /* return to normal-flip */ +#define PS3FB_IOCTL_FSEL _IOW('r', 6, int) /* blit and flip request */ + +#ifndef FBIO_WAITFORVSYNC +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, uint32_t) /* wait for vsync */ +#endif + +struct ps3fb_ioctl_res { + uint32_t xres; /* frame buffer x_size */ + uint32_t yres; /* frame buffer y_size */ + uint32_t xoff; /* margine x */ + uint32_t yoff; /* margine y */ + uint32_t num_frames; /* num of frame buffers */ +}; + +#endif /* _PS3FB_H_ */ + +static vo_info_t info = { + "Framebuffer Device", + "fbdevps3", + "Rasmus Rohde <rohde@duff.dk>", + "" +}; + +LIBVO_EXTERN(fbdevps3) + +extern spe_program_handle_t vo_fbdevps3_scaler; +extern spe_program_handle_t vo_fbdevps3_yuv2rgb; + +static const char *spe_yuv2rgb_filename = "vo_fbdevps3_yuv2rgb"; +static const char *spe_scaler_filename = "vo_fbdevps3_scaler"; +static const char *fb_dev_name = "/dev/fb0"; +static int fb_dev_fd; +struct ps3fb_ioctl_res res; +static struct fb_var_screeninfo fb_vinfo; +static struct fb_fix_screeninfo fb_finfo; +static int fb_tty_fd; + +static int fb_line_len; +static size_t fb_size; +static void *frame_buffer; +static void *center; + +static int fb_pixel_size; +static int in_width; +static int in_height; +static uint32_t img_format; + +static unsigned int fb_page; + +/* Here comes data for the SPU yuv2rgb */ +static int init_spu_yuv2rgb(int w, int h); +static spe_context_ptr_t spe_context_yuv2rgb; +static spe_event_handler_ptr_t spe_event_yuv2rgb; +static img_args *pd_yuv2rgb; +static int yuv_thread_running; + + +/* Here comes data for the SPU scaler and blitter */ +static int init_spu_scaler(int orig_w, int w, int h); +static spe_context_ptr_t spe_context_scaler; +static spe_event_handler_ptr_t spe_event_scaler; +static int spe_init_done_scaler; +static int spe_init_done_yuv2rgb; +static int scaler_thread_running; + +typedef struct { + unsigned long long in[2]; + unsigned long long out[2]; + + unsigned int in_width; // Must be a multiple of 4 + float scale; + unsigned int out_height; + unsigned int out_width_total; // Must be a multiple of 4 + unsigned int out_width_overscan; // Must be a multiple of 4 +} __attribute__((aligned(16))) spe_data_scaler; + +static spe_data_scaler *pd_scaler; +static uint8_t *temp_input; +static uint8_t *temp_input_yuv; + +static int preinit(const char *vo_subdevice) +{ + if ((fb_dev_fd = open(fb_dev_name, O_RDWR)) == -1) { + mp_msg(MSGT_VO, MSGL_ERR, "Can't open %s: %s\n", + fb_dev_name, strerror(errno)); + goto err_out; + } + if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) { + mp_msg(MSGT_VO, MSGL_ERR, "Can't get VSCREENINFO: %s\n", + strerror(errno)); + goto err_out_fd; + } + + if ((fb_tty_fd = open("/dev/tty", O_RDWR)) < 0) { + mp_msg(MSGT_VO, MSGL_ERR, "notice: Can't open /dev/tty: %s\n", + strerror(errno)); + } + + fb_pixel_size = fb_vinfo.bits_per_pixel / 8; + fb_page = 0; + + return 0; + +err_out_fd: + close(fb_dev_fd); +err_out: + return -1; +} + +static void uninit(void) +{ + if(spe_init_done_scaler) { + int mbox_data = -1; + int retries = 3; + struct spe_event_unit event; + + // Stop the SPU + spe_in_mbox_write(spe_context_scaler, &mbox_data, 1, + SPE_MBOX_ANY_NONBLOCKING); + + while(retries) { + if(spe_event_wait(spe_event_scaler, &event, 1, -1) <= 0 + || !(event.events & SPE_EVENT_OUT_INTR_MBOX)) { + retries--; + } else { + break; + } + } + + spe_init_done_scaler = 0; + } + + if(spe_init_done_yuv2rgb) { + int mbox_data = 0; + int retries = 3; + struct spe_event_unit event; + + // Stop the SPU + spe_in_mbox_write(spe_context_yuv2rgb, &mbox_data, 1, + SPE_MBOX_ANY_NONBLOCKING); + + while(retries) { + if(spe_event_wait(spe_event_yuv2rgb, &event, 1, -1) <= 0 + || !(event.events & SPE_EVENT_OUT_INTR_MBOX)) { + retries--; + } else { + break; + } + } + + spe_init_done_yuv2rgb = 0; + } + + if (fb_tty_fd >= 0) { + if (ioctl(fb_tty_fd, KDSETMODE, KD_TEXT) < 0) + mp_msg(MSGT_VO, MSGL_WARN, "Can't restore text mode" + ": %s\n", strerror(errno)); + } + + ioctl(fb_dev_fd, PS3FB_IOCTL_OFF, 0); + + close(fb_tty_fd); + close(fb_dev_fd); + if(frame_buffer) munmap(frame_buffer, fb_size); + frame_buffer = NULL; + + if(temp_input) { + free(temp_input); + temp_input = NULL; + } + + if(temp_input_yuv) { + free(temp_input_yuv); + temp_input_yuv = NULL; + } + + if(pd_scaler) { + free(pd_scaler); + pd_scaler = NULL; + } + + if(pd_yuv2rgb) { + free(pd_yuv2rgb); + pd_yuv2rgb = NULL; + } +} + +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 size_temp_input; + + if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) { + mp_msg(MSGT_VO, MSGL_V, "Can't set graphics mode: %s\n", + strerror(errno)); + close(fb_tty_fd); + fb_tty_fd = -1; + } else { + mp_msg(MSGT_VO, MSGL_V, "Unable to open tty, which means I " + "cannot disable the blinking cursor\n"); + } + + if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) { + mp_msg(MSGT_VO, MSGL_ERR, "Can't get FSCREENINFO: %s\n", + strerror(errno)); + return 1; + } + + if (ioctl(fb_dev_fd, PS3FB_IOCTL_SCREENINFO, &res) < 0) { + mp_msg(MSGT_VO, MSGL_ERR, "Can't get PS3FB_IOCTL_SCREENINFO" + ": %s\n", strerror(errno)); + return 1; + } + + + fb_line_len = fb_finfo.line_length; + fb_size = fb_finfo.smem_len; + + frame_buffer = (uint8_t *) mmap(0, fb_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fb_dev_fd, 0); + if (frame_buffer == (uint8_t *) -1) { + mp_msg(MSGT_VO, MSGL_ERR, "Can't mmap %s: %s\n", + fb_dev_name, strerror(errno)); + return 1; + } + + memset(frame_buffer, 0, fb_size); + + ioctl(fb_dev_fd, PS3FB_IOCTL_ON, 0); + + in_width = width; + in_height = height; + + width = ((width+15) & (~0xf)); + + posix_memalign(&temp_input_yuv, 128, width*height*2+width*height); + + size_temp_input = width*height*fb_pixel_size*2; + posix_memalign(&temp_input, 128, size_temp_input); + memset(temp_input, 0, size_temp_input); + + if(init_spu_scaler(in_width, width, height) < 0) { + return 1; + } + + if(init_spu_yuv2rgb(width, height) < 0) { + return 1; + } + + center = temp_input + + ( in_width / 2 ) * fb_pixel_size + + ( in_height / 2 ) * fb_line_len; + + img_format = format; + + return 0; +} + +struct spe_thread_data { + void *context; + void *pd; + char *name; + unsigned long size; +}; + +static void *spe_thread(void *data) +{ + struct spe_thread_data *spe_data = (struct spe_thread_data *)data; + unsigned int runflags = 0; + unsigned int entry = SPE_DEFAULT_ENTRY; + + int status = spe_context_run(spe_data->context, &entry, runflags, + spe_data->pd, (void *)spe_data->size, + NULL); + + free(data); + if(status < 0) { + mp_msg(MSGT_VO, MSGL_ERR, "OUCH - could not run SPE thread " + "%s\n", spe_data->name); + return 0; + } + + return 0; +} + +static void wait_yuv2rgb_conversion(void) +{ + if(yuv_thread_running > 0) { + int retries = 3, mbox_data; + + while(retries) { + struct spe_event_unit event; + if(spe_event_wait(spe_event_yuv2rgb, &event, 1, -1) <= 0 + || !(event.events & SPE_EVENT_OUT_INTR_MBOX)) { + retries--; + } else { + break; + } + } + if(retries == 0) { + mp_msg(MSGT_VO, MSGL_WARN, "Failed to receive yuv2rgb " + "result from SPE\n"); + } + + spe_out_intr_mbox_read(spe_context_yuv2rgb, &mbox_data, 1, + SPE_MBOX_ANY_NONBLOCKING); + yuv_thread_running--; + + if(yuv_thread_running > 0) { + mp_msg(MSGT_VO, MSGL_WARN, "yuv_thread_running was not" + " 0 as expected but %d\n", yuv_thread_running); + } + } +} + +static void wait_scaler(void) +{ + if(scaler_thread_running > 0) { + int retries = 3, mbox_data; + + while(retries) { + struct spe_event_unit event; + if(spe_event_wait(spe_event_scaler, &event, 1, -1) <= 0 + || !(event.events & SPE_EVENT_OUT_INTR_MBOX)) { + retries--; + } else { + break; + } + } + if(retries == 0) { + mp_msg(MSGT_VO, MSGL_WARN, "Failed to receive scaling" + " result from SPE\n"); + } + + spe_out_intr_mbox_read(spe_context_scaler, &mbox_data, 1, + SPE_MBOX_ANY_NONBLOCKING); + + scaler_thread_running--; + + if(scaler_thread_running > 0) { + mp_msg(MSGT_VO, MSGL_WARN, "scaler_thread_running was" + " not 0 as expected but %d\n", + scaler_thread_running); + } + } +} + +static int init_spu_yuv2rgb(int width, int height) +{ + int retries = 3, mbox_data; + struct spe_event_unit event; + unsigned int createflags = SPE_EVENTS_ENABLE; + spe_program_handle_t *software_yuv2rgb_spe2; + int status, thread_id; + pthread_t pts; + struct spe_thread_data *thread_data; + unsigned char use_external_code = 0; + + // Fill in the struct + posix_memalign(&pd_yuv2rgb, 128,sizeof(*pd_yuv2rgb)); + + pd_yuv2rgb->width=width; + pd_yuv2rgb->height=height; + pd_yuv2rgb->Output[0]=(unsigned long long)temp_input; + pd_yuv2rgb->Output[1]=(unsigned long long)temp_input+width*height*4; + pd_yuv2rgb->Ystart[0] = (unsigned long long)temp_input_yuv; + pd_yuv2rgb->Ustart[0] = (unsigned long long)temp_input_yuv+width*height; + pd_yuv2rgb->Vstart[0] = (unsigned long long)temp_input_yuv + +width*height+width*height/4; + pd_yuv2rgb->Ystart[1] = pd_yuv2rgb->Ystart[0] + +width*height+width*height/2; + pd_yuv2rgb->Ustart[1] = pd_yuv2rgb->Ustart[0] + +width*height+width*height/2; + pd_yuv2rgb->Vstart[1] = pd_yuv2rgb->Vstart[0] + +width*height+width*height/2; + + // Start the SPE + spe_context_yuv2rgb = spe_context_create(createflags, NULL); + + if(!spe_context_yuv2rgb) { + mp_msg(MSGT_VO, MSGL_ERR, "OUCH - could not spawn SPE" + " thread %d\n", errno); + return -1; + } + + // Try and see if we can find an external + software_yuv2rgb_spe2 = spe_image_open(spe_yuv2rgb_filename); + + if(software_yuv2rgb_spe2) { + status = spe_program_load(spe_context_yuv2rgb, + software_yuv2rgb_spe2); + if(status >= 0) { + mp_msg(MSGT_VO, MSGL_INFO, "Using external" + " %s\n", spe_yuv2rgb_filename); + use_external_code = 1; + } + spe_image_close(software_yuv2rgb_spe2); + } + + if(!use_external_code) { + spe_program_load(spe_context_yuv2rgb, &vo_fbdevps3_yuv2rgb); + } + + thread_data = (struct spe_thread_data *)malloc(sizeof(*thread_data)); + thread_data->context = spe_context_yuv2rgb; + thread_data->pd = pd_yuv2rgb; + thread_data->name = "yuv2rgb"; + thread_data->size = sizeof(*pd_yuv2rgb); + + memset(frame_buffer, 0, fb_vinfo.xres*fb_vinfo.yres*4*2); + + spe_event_yuv2rgb = spe_event_handler_create(); + event.spe = spe_context_yuv2rgb; + event.events = SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_SPE_STOPPED; + status = spe_event_handler_register(spe_event_yuv2rgb, &event); + if(status < 0) { + mp_msg(MSGT_VO, MSGL_ERR, "OUCH - failed to register" + " event handler %d\n", errno); + return -1; + } + + thread_id = pthread_create(&pts, 0, &spe_thread, thread_data); + pthread_detach(pts); + + yuv_thread_running = 1; + wait_yuv2rgb_conversion(); + + spe_init_done_yuv2rgb = 1; + + return 0; +} + +static int init_spu_scaler(int orig_w, int w, int h) +{ + int retries = 3; + int mbox_data = 0; + struct spe_event_unit event; + unsigned int createflags = SPE_EVENTS_ENABLE; + spe_program_handle_t *software_scale_spe2; + int status, thread_id; + pthread_t pts; + struct spe_thread_data *thread_data; + unsigned char use_external_code = 0; + + posix_memalign(&pd_scaler, 16, sizeof(spe_data_scaler)); + + pd_scaler->in[0] = (unsigned long long)temp_input; + pd_scaler->in[1] = (unsigned long long)(temp_input+w*h*4); + pd_scaler->in_width = w; + pd_scaler->scale = orig_w / (float)(fb_vinfo.xres); + pd_scaler->out_height = (int)(h / pd_scaler->scale); + + pd_scaler->out[0] = (unsigned long long)frame_buffer; + pd_scaler->out_width_total = fb_line_len / fb_pixel_size; + + if(pd_scaler->out_height > fb_vinfo.yres) { + int w_diff; + // We cannot scale to full-screen + pd_scaler->out_height = fb_vinfo.yres; + pd_scaler->scale = h / (float)(fb_vinfo.yres); + pd_scaler->out_width_overscan = pd_scaler->out_width_total + -(int)(orig_w / pd_scaler->scale); + // Make sure we align on an 8 byte boundary + pd_scaler->out_width_overscan = (pd_scaler-> + out_width_overscan+3) & (~7); + w_diff = pd_scaler->out_width_overscan + -(res.xres - fb_vinfo.xres); + if(w_diff > 16) + pd_scaler->out[0] += ((w_diff - 16 + 1) & (~0x3)) + *fb_pixel_size / 2; + } else { + pd_scaler->out_width_overscan = fb_line_len / fb_pixel_size + -fb_vinfo.xres; + } + + if(pd_scaler->out_height < (fb_vinfo.yres)) { + // yres + 8 centers on my tv - may be incorrect for other tvs + pd_scaler->out[0] += fb_line_len* + (((fb_vinfo.yres + 8 - pd_scaler->out_height)/2)&(~3)); + } + + pd_scaler->out[1] = pd_scaler->out[0] + res.xres + * res.yres * fb_pixel_size; + + // Start the SPE + spe_context_scaler = spe_context_create(createflags, NULL); + + if(!spe_context_scaler) { + mp_msg(MSGT_VO, MSGL_ERR, "OUCH - could not spawn SPE" + " thread %d\n", errno); + return -1; + } + + // Try and see if we can find an external + software_scale_spe2 = spe_image_open(spe_scaler_filename); + + if(software_scale_spe2) { + status = spe_program_load(spe_context_scaler, + software_scale_spe2); + if(status >= 0) { + mp_msg(MSGT_VO, MSGL_INFO, "Using external %s\n", + spe_scaler_filename); + use_external_code = 1; + } + + spe_image_close(software_scale_spe2); + } + + if(!use_external_code) { + spe_program_load(spe_context_scaler, &vo_fbdevps3_scaler); + } + + thread_data = (struct spe_thread_data *)malloc(sizeof(*thread_data)); + thread_data->context = spe_context_scaler; + thread_data->pd = pd_scaler; + thread_data->name = "scaler"; + thread_data->size = sizeof(*pd_scaler); + + memset(frame_buffer, 0, fb_vinfo.xres*fb_vinfo.yres*4*2); + + spe_event_scaler = spe_event_handler_create(); + event.spe = spe_context_scaler; + event.events = SPE_EVENT_OUT_INTR_MBOX | SPE_EVENT_SPE_STOPPED; + status = spe_event_handler_register(spe_event_scaler, &event); + if(status < 0) { + mp_msg(MSGT_VO, MSGL_ERR, "OUCH - failed to register event" + " handler %d\n", errno); + return -1; + } + + thread_id = pthread_create(&pts, 0, &spe_thread, thread_data); + pthread_detach(pts); + + scaler_thread_running = 1; + wait_scaler(); + + spe_init_done_scaler = 1; + + return 0; +} + +static void flip_page(void) +{ + unsigned int wait_vsync = 0; + + ioctl(fb_dev_fd, FBIO_WAITFORVSYNC, &wait_vsync); + ioctl(fb_dev_fd, PS3FB_IOCTL_FSEL, &fb_page); +} + +static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, + int y) +{ + if ((img_format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { + unsigned int mbox_data; + + wait_scaler(); + + fb_page ^= 1; + memcpy((void *)pd_scaler->in[fb_page], src[0], + w*h*fb_pixel_size); + + // Start the SPE + mbox_data = 1 + fb_page; + spe_in_mbox_write(spe_context_scaler, &mbox_data, 1, + SPE_MBOX_ANY_NONBLOCKING); + scaler_thread_running++; + } else { + memcpy((void *)pd_yuv2rgb->Ystart[fb_page^1]+stride[0]*y, + src[0], stride[0]*h); + memcpy((void *)pd_yuv2rgb->Ustart[fb_page^1]+stride[1]*y/2, + src[1], stride[1]*h/2); + memcpy((void *)pd_yuv2rgb->Vstart[fb_page^1]+stride[2]*y/2, + src[2], stride[2]*h/2); + } +} + +static void check_events(void) +{ +} + +static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, + unsigned char *srca, int stride) +{ + unsigned char *dst; + + dst = center + fb_line_len * y0 + fb_pixel_size * x0; + + vo_draw_alpha_rgb24(w, h, src, srca, stride, dst, fb_line_len); +} + +static void draw_osd(void) +{ + vo_draw_text(in_width, in_height, draw_alpha); +} + +static uint32_t get_image(mp_image_t *mpi) +{ + if (mpi->flags & MP_IMGFLAG_READABLE) return VO_FALSE; + if (mpi->type == MP_IMGTYPE_IP || mpi->type == MP_IMGTYPE_IPB) + return VO_FALSE; // we can not provide readable buffers + + if (!IMGFMT_IS_BGR(mpi->imgfmt) || + ((mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) + || (mpi->flags & MP_IMGFLAG_PLANAR) + || (mpi->flags & MP_IMGFLAG_YUV) + || (mpi->width != in_width) + || (mpi->height != in_height) + ) + return(VO_FALSE); + + mpi->planes[0] = center; + mpi->stride[0] = fb_line_len; + mpi->flags |= MP_IMGFLAG_DIRECT; + return(VO_TRUE); +} + +static int draw_frame(uint8_t *src[]) +{ + return 1; +} + +static int query_format(uint32_t format) +{ + if ((format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { + int bpp = format & 0xff; + + if (bpp == 32) + return VFCAP_ACCEPT_STRIDE | VFCAP_CSP_SUPPORTED + | VFCAP_CSP_SUPPORTED_BY_HW; + } else if(format == IMGFMT_YV12 || + format == IMGFMT_I420 || + format == IMGFMT_IYUV) { + return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW + | VFCAP_ACCEPT_STRIDE; + } + + return 0; +} + +int draw_image(mp_image_t *img) +{ + int mbox_data; + + if (img->flags & MP_IMGFLAG_DRAW_CALLBACK) { + wait_yuv2rgb_conversion(); + wait_scaler(); + + mbox_data = 1 + fb_page; + spe_in_mbox_write(spe_context_scaler, &mbox_data, 1, + SPE_MBOX_ANY_NONBLOCKING); + scaler_thread_running++; + + fb_page ^= 1; + + mbox_data = fb_page; + spe_in_mbox_write(spe_context_yuv2rgb, &mbox_data, 1, + SPE_MBOX_ANY_NONBLOCKING); + + yuv_thread_running++; + return VO_TRUE; + } + + return VO_ERROR; +} + +static int control(uint32_t request, void *data, ...) +{ + switch (request) { + case VOCTRL_GET_IMAGE: + return get_image(data); + case VOCTRL_DRAW_IMAGE: + return draw_image((mp_image_t *)data); + case VOCTRL_QUERY_FORMAT: + return query_format(*((uint32_t*)data)); + } + return VO_NOTIMPL; +} Index: configure =================================================================== --- configure (revision 23402) +++ configure (working copy) @@ -296,6 +296,8 @@ --disable-libpostproc_so disable shared libpostproc [autodetect] --disable-libavcodec_mpegaudio_hp disable high precision audio decoding in libavcodec [enabled] + --disable-libspe2 disable libspe2 [autodetect] + --disable-spu disable building spu specific code [autodetect] --disable-tremor-internal disable internal Tremor [enabled] --enable-tremor-low enable lower accuracy internal Tremor [disabled] --enable-tremor-external enable external Tremor [autodetect] @@ -651,6 +653,8 @@ _stream_cache=yes _def_stream_cache="#define USE_STREAM_CACHE 1" _need_shmem=yes +_libspe2=auto +_spu=auto for ac_option do case "$ac_option" in --help|-help|-h) @@ -1002,6 +1006,10 @@ --disable-libpostproc_so) _libpostproc_so=no ;; --enable-libavcodec_mpegaudio_hp) _libavcodec_mpegaudio_hp=yes ;; --disable-libavcodec_mpegaudio_hp) _libavcodec_mpegaudio_hp=no ;; + --enable-libspe2) _libspe2=yes ;; + --disable-libspe2) _libspe2=no ;; + --enable-spu) _spu=yes ;; + --disable-spu) _spu=no ;; --enable-lirc) _lirc=yes ;; --disable-lirc) _lirc=no ;; @@ -1960,7 +1968,7 @@ iproc='ppc' proc='' _march='' - _mcpu='' + _mcpu='-mcpu=cell' _optimizing='' _altivec=no @@ -5548,7 +5556,57 @@ fi echores "$_zlib" +echocheck "libspe2" +if test "$_libspe2" = auto ; then +cat > $TMPC << EOF +#include <libspe2.h> +int main(void) { spe_program_handle_t *p=spe_image_open("t"); return 0; } +EOF + _libspe2=no + if $_pkg_config --exists libspe2 ; then + _inc_libspe2=`$_pkg_config --cflags libspe2` + _ld_tmp=`$_pkg_config --libs libspe2` + cc_check $_inc_libspe2 $_ld_tmp && _ld_extra="$_ld_extra $_ld_tmp" \ + && _libspe2=yes + fi +fi +if test "$_libspe2" = yes ; then + _def_libspe2='#define HAVE_LIBSPE2 1' +else + _def_libspe2='#undef HAVE_LIBSPE2' +fi +echores "$_libspe2" +echocheck "spu support" +if test "$_spu" = auto ; then +cat > $TMPC << EOF +int main(unsigned long long spe_id, unsigned long long program_data_ea, unsigned +long long env) { asm("ceqi \$2, \$1, 0"); return 0; } +EOF + _spu=no + _spucc_found=no + _realcc=$_cc + for _spucc in spu-gcc spu-elf-gcc ; do + rm -f "$TMPO" + echo "$_spucc $TMPC -o $TMPO" >> "$TMPLOG" + $_spucc $TMPC -o $TMPO >> "$TMPLOG" 2>&1 && _spucc_found=yes + test "$_spucc_found" = yes && break + done + if test "$_spucc_found" = yes ; then + for _embedspu in ppu-embedspu embedspu ; do + $_embedspu test "$TMPO" "$TMPC" >> "$TMPLOG" 2>&1 && _spu=yes + test "$_spu" = yes && break + done + fi +fi + +if test "$_spu" = yes ; then + _def_spu='#define HAVE_SPU 1' +else + _def_spu='#undef HAVE_SPU' +fi +echores "$_spu" + echocheck "RTC" if test "$_rtc" = auto ; then cat > $TMPC << EOF @@ -7610,6 +7668,10 @@ CONFIG_XVID=$_lavc_xvid CONFIG_X264=$_lavc_x264 CONFIG_ZLIB=$_zlib +CONFIG_LIBSPE2=$_libspe2 +CONFIG_SPU=$_spu +SPUCC=$_spucc +EMBEDSPU=$_embedspu CONFIG_GPL=yes CONFIG_ENCODERS=$_mencoder CONFIG_MUXERS=$_mencoder @@ -7878,6 +7940,18 @@ #define CONFIG_ZLIB 1 #endif +/* Define this if you have libspe2 */ +$_def_libspe2 +#ifdef HAVE_LIBSPE2 +#define CONFIG_LIBSPE2 1 +#endif + +/* Define this if you have spu support */ +$_def_spu +#ifdef HAVE_SPU +#define CONFIG_SPU 1 +#endif + /* Define this if you have shm support */ $_def_shm
Hello, On Tue, May 29, 2007 at 10:13:42AM +0200, Luca Barbato wrote: [...]
- make the vo behave like the gl one
Since I as the gl maintainer don't quite get what you mean, can you explain what exactly you're thinking of (yes, I read the previous comments on that subject). Greetings, Reimar Doeffinger
On 29/05/07, Reimar Doeffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de> wrote:
Hello, On Tue, May 29, 2007 at 10:13:42AM +0200, Luca Barbato wrote: [...]
- make the vo behave like the gl one
Since I as the gl maintainer don't quite get what you mean, can you explain what exactly you're thinking of (yes, I read the previous comments on that subject).
Behaviour with respect to changing video size modes, fullscreen scaled and location on screen. My new spu yuv scaler i hope to be finished today should be enough general purpose to handle this, however scaling down to 1/16 you might run into troubles. and it must scale to a width/16 and height/4. You would simply only need to pass a command to it telling it to update its parameters. Although i dont know how this is done in the gl vo. However it will have to tell the Xserver to redraw everything around it as its working on the framebuffer!
Greetings, Reimar Doeffinger _______________________________________________ MPlayer-dev-eng mailing list MPlayer-dev-eng@mplayerhq.hu http://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
Cheers -- Kristian Jerpetjøn Tlf: +4721694436 Mob +4792822774 Email: kristian.jerpetjoen@gmail.com
I attach here the original yuv colorspace code from patch 01 relicensed under lgpl as well as bsdv2 it performs slightly better than the version you are currently running. I will add further improvements with some software pipelining once im done with the yuv scaler this should bring the performance higher than the 300FPS @1080p it has been tested to. I have changed the iargs->width to iargs->dstW and same for height to be able to reuse the same header for the yuv scaler which is nearing completion this is also familiar names from libswscale i belive. There is no ppu side implementation as the example back in rev01 should suffice. I hope this will come to use! Cheers Kristian Jerpetjøn Tlf: +4721694436 Mob +4792822774 Email: kristian.jerpetjoen@gmail.com
On Tue, May 29, 2007 at 11:31:21PM +0200, Kristian Jerpetjøn wrote:
I attach here the original yuv colorspace code from patch 01 relicensed under lgpl as well as bsdv2
What is the BSDv2 license? I've never heard of such a thing. Diego
On Thu, 31 May 2007 18:03:18 +0200 Diego Biurrun <diego@biurrun.de> wrote:
What is the BSDv2 license? I've never heard of such a thing.
The BSD license, without the (GPL-incompatible) advertising clause.
On 31/05/07, RC <rcooley@spamcop.net> wrote:
On Thu, 31 May 2007 18:03:18 +0200 Diego Biurrun <diego@biurrun.de> wrote:
What is the BSDv2 license? I've never heard of such a thing.
The BSD license, without the (GPL-incompatible) advertising clause. if its compatible with mplayer i might exclude lgpl from my yuv scaler and the yuvscaler that outputs rgb probably both these will be in early beta releases available within a few weeks. _______________________________________________ MPlayer-dev-eng mailing list MPlayer-dev-eng@mplayerhq.hu http://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
-- Kristian Jerpetjøn Email: kristian.jerpetjoen@gmail.com
Reimar Doeffinger wrote:
Hello, On Tue, May 29, 2007 at 10:13:42AM +0200, Luca Barbato wrote: [...]
- make the vo behave like the gl one
Since I as the gl maintainer don't quite get what you mean, can you explain what exactly you're thinking of (yes, I read the previous comments on that subject).
the vo could have similar options (customprog, yuv, lscale) so I plan to have it consistent with gl, Kristian pointed other similarities. lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero
Hello, On Tue, May 29, 2007 at 10:13:42AM +0200, Luca Barbato wrote:
Luca Barbato wrote:
Hopefully I'll write something about spu/cell toolchain support soonish.
Here the initial kludge.
What's missing:
- make the vo behave like a normal vo configure/build wise - make the vo independent to the spu scaler/converter - make the vo behave like the gl one
What should be done:
- move the scaler/converter to swscaler on a second time (pending swscaler clenaup)
I integrated this into the ps3vo branch of the git-repository at http://www1.mplayerhq.hu/~reimar/MPlayer.git/, if you send me patches against that I will happily integrate them as well. Greetings, Reimar Döffinger
Rasmus Rohde wrote:
Okie - I've put together an updated patch which also detects if we have spu-gcc and ppu-embedspu available. Furthermore I've included my current version of vo_fbdevps3.c together with the SPU code that does color conversion and scaling.
+echocheck "spugcc" +if test "$_spugcc" = auto ; then +cat > $TMPC << EOF +int main(unsigned long long spe_id, unsigned long long program_data_ea, unsigned +long long env) { asm("ceqi \$2, \$1, 0"); return 0; } +EOF + _spugcc=no + + rm -f "$TMPO" + echo "spu-gcc -o $TMPO $TMPC" >> "$TMPLOG" + spu-gcc -o "$TMPO" "$TMPC" >> "$TMPLOG" 2>&1 && ppu-embedspu test "$TMPO" "$TMPC" && _spugcc=yes +fi +if test "$_spugcc" = yes ; then + _def_spugcc='#define HAVE_SPUGCC 1' +else + _def_spugcc='#undef HAVE_SPUGCC' +fi +echores "$_spugcc" grr, spu-gcc is a bad alias for spu-elf-gcc even worse ppu-${something} is a quick hack from the start, you should expect to have embedspu from the current local/cross toolchain (that is either plain embedspu or the same prefix you have in the compiler). Since they won't be out of business soon, you may iterate across spu- spu-elf- and probably soon gcc -mspu to check for an spu compatible compiler (xlc should be treated on a later time IMHO) same for embedspu with "", ppu-, ${_cc//gcc} or something similar/smarter. lu -- Luca Barbato Gentoo/linux Gentoo/PPC http://dev.gentoo.org/~lu_zero
participants (7)
-
Diego Biurrun -
Kristian Jerpetjøn -
Luca Barbato -
Rasmus Rohde -
RC -
Reimar Doeffinger -
Reimar Döffinger