Screenshot instructions:
Windows
Mac
Red Hat Linux
Ubuntu
Click URL instructions:
Right-click on ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)
From: <walken@zo...> - 2001-02-12 04:28:13
|
Hi, On Mon, Feb 12, 2001 at 05:13:41AM +0100, Guenter Bartsch wrote: > - system clock is used as timer device instead of audio hardware/driver Yay ! :) I like that > - libmpeg2 update (Michel: the new libvo interface looks nice, > I think the diffs needed for xine should be rather small :-)) Double-yay ! :) On my side I plan to release mpeg2dec 0.2.0 sometime this week, so if you sync with the current cvs code you should not have any problems syncing again with 0.2.0. The only libmpeg2 change I have left before release is to make libmpeg2 fully reentrant, which should come at no speed cost since we're already 90% there. After 0.2.0 I plan so start integrating some simple syncing framework in mpeg2dec, so that I can at least play at the right speed. I'll send more info about that on livid-mpeg2dec. But it will definitely help me to look at your patches I guess :) > There has been a lot of talk about porting efforts to other platforms that > linux/freebsd on x86 architectures. I really consider this important, > however, I think we should schedule that for the 0.5.x series of > xine. First I'd like to see the new code getting somewhat stable again, > then we can go for other hardware/os platforms. But that doesn't mean that > anybody should stop his porting efforts - keep up the good work, but don't > be too disappointed if your patches won't go into xine CVS at this point. If anyone has optimizations for MC, IDCT or color conversion, send these to me :) I'd love to have altivec optimizations for starters. Regards, -- Michel "Walken" LESPINASSE Of course I think I'm right. If I thought I was wrong, I'd change my mind. |
From: Guenter Bartsch <bartscgr@st...> - 2001-02-12 04:13:14
|
Hi everyone, yes, it's true, I finally did a cvs commit and now the new architecture is in CVS. Much has changed, for details see below. A notice to end-users who are following the xine CVS (and are used to get mature code from there ;)) : the code I just checked in is still und heavy developement, don't expect it to be usefull [yet]. This code is meant for debugging and improving, not for testing only. If you try it and tell me it doesn't work, I'll happily ignore you (since I already know); if you try it and send me a patch to make it work again on your configuration you're welcome. Ok, now the details. What's new: - system clock is used as timer device instead of audio hardware/driver - multi-threaded architecture, xine gets idle when there's more CPU power than needed - libmpg123 has a new interface similar to libac3 what's broken : - spu decoder: yes, it was me, I broke it - sorry folks! I didn't want to wait any longer with my commit, so I checked it in as it is. getting it to work again shouldn't be too difficult; we first need to provide vpts calculation functions in metronom for the subtitles - alsa audio driver - the avi demuxer needs some work - anybody on this list in the know with avi and how syncing really works in these files? - syncfb video driver next things on the TODO list: - libmpeg2 update (Michel: the new libvo interface looks nice, I think the diffs needed for xine should be rather small :-)) - new video_out_xshm (including subtitle support and scaling) - as a proof of concept for the new architecture: audio_esd_out (yes, that should be possible now), video_out_xremote There has been a lot of talk about porting efforts to other platforms that linux/freebsd on x86 architectures. I really consider this important, however, I think we should schedule that for the 0.5.x series of xine. First I'd like to see the new code getting somewhat stable again, then we can go for other hardware/os platforms. But that doesn't mean that anybody should stop his porting efforts - keep up the good work, but don't be too disappointed if your patches won't go into xine CVS at this point. Cheers, Guenter |
From: <walken@zo...> - 2001-02-12 04:28:13
|
Hi, On Mon, Feb 12, 2001 at 05:13:41AM +0100, Guenter Bartsch wrote: > - system clock is used as timer device instead of audio hardware/driver Yay ! :) I like that > - libmpeg2 update (Michel: the new libvo interface looks nice, > I think the diffs needed for xine should be rather small :-)) Double-yay ! :) On my side I plan to release mpeg2dec 0.2.0 sometime this week, so if you sync with the current cvs code you should not have any problems syncing again with 0.2.0. The only libmpeg2 change I have left before release is to make libmpeg2 fully reentrant, which should come at no speed cost since we're already 90% there. After 0.2.0 I plan so start integrating some simple syncing framework in mpeg2dec, so that I can at least play at the right speed. I'll send more info about that on livid-mpeg2dec. But it will definitely help me to look at your patches I guess :) > There has been a lot of talk about porting efforts to other platforms that > linux/freebsd on x86 architectures. I really consider this important, > however, I think we should schedule that for the 0.5.x series of > xine. First I'd like to see the new code getting somewhat stable again, > then we can go for other hardware/os platforms. But that doesn't mean that > anybody should stop his porting efforts - keep up the good work, but don't > be too disappointed if your patches won't go into xine CVS at this point. If anyone has optimizations for MC, IDCT or color conversion, send these to me :) I'd love to have altivec optimizations for starters. Regards, -- Michel "Walken" LESPINASSE Of course I think I'm right. If I thought I was wrong, I'd change my mind. |
From: Rich Wareham <rjw57@ca...> - 2001-02-12 17:23:25
|
On Monday 12 February 2001 4:13 am, you wrote: > - spu decoder: yes, it was me, I broke it - sorry folks! > I didn't want to wait any longer with my commit, so I checked it in > as it is. Well fixed it. Take a look below. Comments? If its OK with everyone, I'll check it in tommorrow morning. diff -ur cvs/xine/libspudec/spudec.c xine/libspudec/spudec.c --- cvs/xine/libspudec/spudec.c Mon Feb 12 13:36:21 2001 +++ xine/libspudec/spudec.c Mon Feb 12 16:59:58 2001 @@ -59,18 +59,6 @@ clut_t *clut; } spudec_globals; -unsigned char mask_pal[3][4] = { - { 0xff, 0x00, 0x00, 0x00 }, - { 0xff, 0x00, 0x00, 0x00 }, - { 0xff, 0x00, 0x00, 0x00 } -}; - -unsigned char overlay_pal[3][4] = { - { 0x00, 0x10, 0x7d, 0xeb }, - { 0x00, 0x80, 0x80, 0x80 }, - { 0x00, 0x80, 0x80, 0x80 } -}; - clut_t *palette[4] = { NULL, NULL, NULL, NULL }; @@ -149,13 +137,16 @@ void spudec_tick() { uint32_t pts; + if(!gSpudec.bInitialised) + return; - /*pts = metronom_get_sync_pts(); FIXME */ - pts =0 ; + pts = metronom_got_spu_packet(0); /* See if we have any SPUs queued */ if(spudec_queue_size != 0) { - spudec_packet *p = spudec_peek_next_packet(); + spudec_packet *p; + + p = spudec_peek_next_packet(); if(pts >= p->pts) { /* Process */ p = spudec_get_next_packet(); @@ -167,7 +158,7 @@ free(p->packet); free(p); } - } + } if((gSpudec.geom.bIsVisible) && (pts - gSpudec.lifetime >= gSpudec.displayPTS)) { gSpudec.geom.bIsVisible = 0; @@ -507,6 +498,7 @@ size = (gSpudec.packet[0]<<8) + gSpudec.packet[1] - gSpudec.packet_size; } } + memcpy(gSpudec.packet + gSpudec.packet_size, data, size); gSpudec.packet_size += size; Only in xine/libw32dll/wine: Makefile.in diff -ur cvs/xine/metronom.c xine/metronom.c --- cvs/xine/metronom.c Mon Feb 12 13:36:20 2001 +++ xine/metronom.c Mon Feb 12 16:06:10 2001 @@ -96,6 +96,12 @@ } +uint32_t metronom_got_spu_packet (uint32_t pts) { + /* FIXME: Nasty hack */ + + return gMetronom.sync_pts; +} + uint32_t metronom_got_video_frame (uint32_t pts) { uint32_t vpts; diff -ur cvs/xine/metronom.h xine/metronom.h --- cvs/xine/metronom.h Mon Feb 12 13:36:20 2001 +++ xine/metronom.h Mon Feb 12 16:45:38 2001 @@ -87,6 +87,17 @@ uint32_t metronom_got_audio_samples (uint32_t pts, uint32_t nsamples); /* + * called by SPU decoder whenever a packet is delivered to it + * + * parameter pts : pts for SPU packet if known, 0 otherwise + * + * return value: virtual pts for SPU packet + * + */ + +uint32_t metronom_got_spu_packet (uint32_t pts); + +/* * **************************************** * master clock functions * **************************************** diff -ur cvs/xine/video_out/video_out.c xine/video_out/video_out.c --- cvs/xine/video_out/video_out.c Mon Feb 12 13:36:22 2001 +++ xine/video_out/video_out.c Mon Feb 12 17:01:03 2001 @@ -37,6 +37,7 @@ #include "metronom.h" #include "monitor.h" #include "../libmpeg2/mpeg2.h" +#include "../libspudec/spudec.h" #define NUM_BUFFERS 20 @@ -60,6 +61,7 @@ int video_step; int pts_per_half_frame; + int format; /* statistics */ @@ -74,7 +76,16 @@ int bDisplayThreadRun; int display_window_visible; + + /* overlay images */ + + vo_image_buffer_t *overlay_image; + vo_image_buffer_t *mask_image; + int bOverlayImage; + + /* SPU */ + spudec_geometry *spu_geom; } vo_priv_t; vo_driver_t *gVideoDriver; @@ -225,9 +236,23 @@ gVO.width = width; gVO.height = height; + gVO.format = format; gVO.video_step = video_step; gVO.pts_per_half_frame = gVO.video_step/2; + + /* Create overlay images */ + if(gVO.overlay_image != NULL) + gVideoDriver->dispose_image_buffer (gVO.overlay_image); + if(gVO.mask_image != NULL) + gVideoDriver->dispose_image_buffer (gVO.mask_image); + + gVO.overlay_image = gVideoDriver->alloc_image_buffer (); + gVO.mask_image = gVideoDriver->alloc_image_buffer (); + + gVO.bOverlayImage = spudec_set_images(gVO.overlay_image, gVO.mask_image, + width, height, format); + metronom_set_video_rate (gVO.video_step); } @@ -502,9 +527,130 @@ xprintf (VERBOSE|VIDEO, "video_out: ALERT! frame was not locked for display queue\n"); img->bDisplayLock = 0; pthread_mutex_unlock (&img->mutex); - + + /* + * Mix in SPU + */ + + /* Tick SPUdec */ + spudec_tick(); + + if(gVO.bOverlayImage) { + /* This code is pretty nasty but quite quick which is important here! */ + /* APPROACH: Since 32bit processors hande data, well 32bits at a time, + * we overlay the image word by word rather than byte by byte and then + * tidy up the odd bytes at the end. This effectively cuts the number of + * loop itterations by a factor of 4. */ + + /* FIXME: Optimise for 64bit machines as well? */ + + if((gVO.spu_geom->bIsVisible) && + (gVO.format == IMGFMT_YV12)) { + /* Overlay the image. */ + long i, off; + uint8_t *img_l_8, *ovl_l_8, *msk_l_8; + uint32_t *img_l_32, *ovl_l_32, *msk_l_32; + uint8_t *img_y_8, *ovl_y_8, *msk_y_8; + uint32_t *img_y_32, *ovl_y_32, *msk_y_32; + uint8_t *img_v_8, *ovl_v_8, *msk_v_8; + uint32_t *img_v_32, *ovl_v_32, *msk_v_32; + + img_l_8 = img->mem[0]; + ovl_l_8 = gVO.overlay_image->mem[0]; + msk_l_8 = gVO.mask_image->mem[0]; + img_l_32 = ((uint32_t*)img->mem[0]); + ovl_l_32 = ((uint32_t*)gVO.overlay_image->mem[0]); + msk_l_32 = ((uint32_t*)gVO.mask_image->mem[0]); + img_y_8 = img->mem[1]; + ovl_y_8 = gVO.overlay_image->mem[1]; + msk_y_8 = gVO.mask_image->mem[1]; + img_y_32 = ((uint32_t*)img->mem[1]); + ovl_y_32 = ((uint32_t*)gVO.overlay_image->mem[1]); + msk_y_32 = ((uint32_t*)gVO.mask_image->mem[1]); + img_v_8 = img->mem[2]; + ovl_v_8 = gVO.overlay_image->mem[2]; + msk_v_8 = gVO.mask_image->mem[2]; + img_v_32 = ((uint32_t*)img->mem[2]); + ovl_v_32 = ((uint32_t*)gVO.overlay_image->mem[2]); + msk_v_32 = ((uint32_t*)gVO.mask_image->mem[2]); + + /* luminance */ + for(i=gVO.width*gVO.spu_geom->start_row; + i<=gVO.width*gVO.spu_geom->end_row; i+=gVO.width) { + /* i is address of begining of line. */ + + /* Firstly, draw the start odd bytes. */ + for(off = i+gVO.spu_geom->start_col; (off & 3) != 0; off++) { + if(msk_l_8[off] != 0xff) { + img_l_8[off] &= msk_l_8[off]; + img_l_8[off] |= ovl_l_8[off]; + } + } + + /* Now words */ + for(; off<=i+gVO.spu_geom->end_col-3; off+=4) { + if(msk_l_32[off>>2] != 0xffffffff) { + img_l_32[off>>2] &= msk_l_32[off>>2]; + img_l_32[off>>2] |= ovl_l_32[off>>2]; + } + } + off -= 4; + + /* Now end odd bytes */ + for(; off<=i+gVO.spu_geom->end_col; off++) { + if(msk_l_8[off] != 0xff) { + img_l_8[off] &= msk_l_8[off]; + img_l_8[off] |= ovl_l_8[off]; + } + } + } + /* colour */ + for(i=(gVO.width>>1)*(gVO.spu_geom->start_row>>1); + i<=(gVO.width>>1)*(gVO.spu_geom->end_row>>1); i+=(gVO.width)>>1) { + /* i is address of begining of line. */ + + /* Firstly, draw the start odd bytes. */ + for(off = i+((gVO.spu_geom->start_col)>>1); (off & 3) != 0; off++) { + if(msk_y_8[off] != 0xff) { + img_y_8[off] &= msk_y_8[off]; + img_y_8[off] |= ovl_y_8[off]; + } + if(msk_v_8[off] != 0xff) { + img_v_8[off] &= msk_v_8[off]; + img_v_8[off] |= ovl_v_8[off]; + } + } + + /* Now words */ + for(; off<=i+((gVO.spu_geom->end_col)>>1)-3; off+=4) { + if(msk_y_32[off>>2] != 0xffffffff) { + img_y_32[off>>2] &= msk_y_32[off>>2]; + img_y_32[off>>2] |= ovl_y_32[off>>2]; + } + if(msk_v_32[off>>2] != 0xffffffff) { + img_v_32[off>>2] &= msk_v_32[off>>2]; + img_v_32[off>>2] |= ovl_v_32[off>>2]; + } + } + off -= 4; + + /* Final end odd bytes */ + for(; off<=i+((gVO.spu_geom->end_col)>>1); off++) { + if(msk_y_8[off] != 0xff) { + img_y_8[off] &= msk_y_8[off]; + img_y_8[off] |= ovl_y_8[off]; + } + if(msk_v_8[off] != 0xff) { + img_v_8[off] &= msk_v_8[off]; + img_v_8[off] |= ovl_v_8[off]; + } + } + } + } + } + + gVideoDriver->display_frame (img); - /* done by video driver now @@ -590,6 +736,10 @@ gVO.free_img_buf_queue = new_img_buf_queue (); gVO.display_img_buf_queue = new_img_buf_queue (); gVO.bInitialized = 0; + gVO.bOverlayImage = 0; + gVO.overlay_image = NULL; + gVO.mask_image = NULL; + gVO.spu_geom = spudec_get_geometry(); gVO.pts_per_half_frame = 3000; gVO.bDisplayThreadRun = 0; gVO.display_window_visible = 1; diff -ur cvs/xine/xine.c xine/xine.c --- cvs/xine/xine.c Mon Feb 12 13:36:20 2001 +++ xine/xine.c Mon Feb 12 17:14:39 2001 @@ -91,6 +91,7 @@ pthread_t mAudioThread; pthread_t mVideoThread; + pthread_t mSPUThread; fifo_buffer_t *mBufAudio; fifo_buffer_t *mBufVideo; @@ -118,6 +119,14 @@ static xine_globals_t gXine; +static unsigned default_palette[16] = { + 0xe18080, 0x2b8080, 0x847b9c, 0x51ef5a, 0x7d8080, 0xb48080, 0xa910a5, + 0x6addca,0xd29210,0x1c76b8,0x50505a,0x30b86d,0x5d4792, + 0x3dafa5,0x718947,0xeb8080 +}; + +static clut_t* default_clut = (clut_t*) default_palette; + void xine_notify_stream_finished () { printf ("xine_notify_stream_finished\n"); @@ -199,6 +208,33 @@ } +void *xine_spu_loop (void *dummy) { + + buf_element_t *pBuf; + int bRunning = 1; + + while (bRunning) { + + pBuf = fifo_buffer_get (gXine.mBufSPU); + + switch (pBuf->nType) { + case BUF_QUIT: + bRunning = 0; + break; + case BUF_RESET: + spudec_reset (); + break; + case BUF_SPU: + spudec_decode(pBuf->pContent, pBuf->nSize, pBuf->nPTS); + break; + } + buffer_pool_free (pBuf); + } + + return NULL; + +} + void *xine_video_loop () { buf_element_t *pBuf; @@ -337,6 +373,22 @@ vo_set_logo_mode (0); /* + * Init CLUT + */ + + if(gXine.mCurInput->get_clut) { + printf("Attempting to obtain CLUT\n"); + gXine.clut = gXine.mCurInput->get_clut(); + } + + if(gXine.clut == NULL) { + printf("No CLUT found, using default (pretty ugly).\n"); + gXine.clut = default_clut; + } + + spudec_init(gXine.clut); + + /* * metronom */ @@ -615,6 +667,16 @@ printf ("xine_init: video thread created\n"); + /* + * init SPU decoder, start SPU thread + */ + + gXine.clut = default_clut; + spudec_init(gXine.clut); + + pthread_create (&gXine.mSPUThread, NULL, xine_spu_loop, NULL) ; + + printf ("xine_init: video thread created\n"); /* * init audio output, start audio thread -- ================================================================== Rich Wareham <rjw57@...> Robinson College, Cambridge, CB3 9AN You could live a better life, if you had a better mind and a better body. ================================================================== |
From: Guenter Bartsch <bartscgr@st...> - 2001-02-13 13:48:41
|
Hi Rich, On Mon, 12 Feb 2001, Rich Wareham wrote: > On Monday 12 February 2001 4:13 am, you wrote: > > > - spu decoder: yes, it was me, I broke it - sorry folks! > > I didn't want to wait any longer with my commit, so I checked it in > > as it is. > > Well fixed it. Take a look below. Comments? If its OK with everyone, I'll > check it in tommorrow morning. looks very clean to me :-) erm, that > printf ("xine_init: video thread created\n"); is a bit misleading, "spu thread created" would be better instead. Apart from that I'm impressed how fast you adapted the SPU stuff to the new architecture (!) One thing we could investigate is the idea to do without a seperate spu-thread and instead let the tick() function do the decoding as well - avoiding the need to buffer the spu data. Whenever tick () is called it could peek at the spu fifo if there's any data older than the current vpts and decode that data thus having the right subtitles for overlay ready after that. Subtitle decoding shouldn't take too long so it could be done in such a "just in time" manner. The question is though if it will give us any real performance upgrade. The next step would be to make the subtitles work in xshm as well - this would require to move the subtitle decoding from display to decoding time so the subtitle overlay could be copied to the rgb buffer during the yuv2rgb conversion. Kepp up your great work, Guenter |
From: Rich Wareham <rjw57@ca...> - 2001-02-13 13:54:52
|
On Tuesday 13 February 2001 1:48 pm, you wrote: > Hi Rich, > > On Mon, 12 Feb 2001, Rich Wareham wrote: > > On Monday 12 February 2001 4:13 am, you wrote: > > > - spu decoder: yes, it was me, I broke it - sorry folks! > > > I didn't want to wait any longer with my commit, so I checked it in > > > as it is. > > > > Well fixed it. Take a look below. Comments? If its OK with everyone, I'll > > check it in tommorrow morning. > > looks very clean to me :-) > > erm, that > > > printf ("xine_init: video thread created\n"); > > is a bit misleading, "spu thread created" would be better instead. Yeah. I noticed that when I was merging. Fixed now. > > Apart from that I'm impressed how fast you adapted the SPU stuff to the > new architecture (!) np [snip] > The next step would be to make the subtitles work in xshm as well - this > would require to move the subtitle decoding from display to decoding time > so the subtitle overlay could be copied to the rgb buffer during the > yuv2rgb conversion. From the POV of video_out, it doesn't care when the decoding is done, jsut that the buffers overlay_image and mask_image contain the correct subtitle images in the correct format. As it is, the SPU decoder can only decode to YUV (although RGB shouldn't be /that/ hard). It would be better to overlay onto the image before conversion but when I tried that I couldn't find any way of detecting if the video decoder had finished with the image (i.e. bits of subtitle kept wandering around due to motion compensation :)). Does the new architecture help this? -- ================================================================== Rich Wareham <rjw57@...> Robinson College, Cambridge, CB3 9AN Go to a movie tonight. Darkness becomes you. ================================================================== |