|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
[RFC] [PATCH] evenly spaced update intervalsThe patch causes frame update intervals sent to the
Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. In combination with other frame rate control patches [1], this enables the user for example to watch a video on a TV set with a VGA-2-SCART-adapter. [1] http://frc.easy-vdr.de/ Signed-off-by: Thomas Hilber <sparkie@...> Signed-off-by: Paul Menzel <paulepanter@...> # HG changeset patch # User Paul Menzel <paulepanter@...> # Date 1242803813 -7200 # Node ID e7bcf392d58c914a91b718ecc739f095fcb2cdb2 # Parent ef6480bf38399c3bc832e554eca1311ddd4385e6 Frame Rate Control patches from Thomas Hilber. diff -r ef6480bf3839 -r e7bcf392d58c src/xine-engine/video_out.c --- a/src/xine-engine/video_out.c Tue May 19 15:43:53 2009 +0100 +++ b/src/xine-engine/video_out.c Wed May 20 09:16:53 2009 +0200 @@ -997,6 +997,65 @@ } } +#define SHOW_FRAME_DEBUG + +#ifdef SHOW_FRAME_DEBUG + +#define MIDDLE 40000 +#define CATCH 10000 + +#define VSF_SUB(a, b, c) \ + if ((a).tv_usec < (b).tv_usec) { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ + } else { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec; \ + } + +#define VSF_TV2USEC(a, b) \ + (b) = (a).tv_sec * 1000000 + (a).tv_usec; + +#define RESET_COUNTERS() \ + cnt = 0; \ + sum = 0; \ + abs_vpts = vpts; \ + last_vpts = img->vpts; + +void +debug_frame_timing(img, vpts) + vo_frame_t *img; + int64_t vpts; +{ + static int sum; + static int cnt; + static int64_t abs_vpts; + static int64_t last_vpts; + static struct timeval t_prev; + + int usec; + struct timeval t; + struct timeval t_now; + + gettimeofday(&t_now, 0); + VSF_SUB(t_now, t_prev, t); + VSF_TV2USEC(t, usec); + t_prev = t_now; + + if (usec < MIDDLE - CATCH + || usec > MIDDLE + CATCH ) { + if (last_vpts) printf("STRAY: %10d\n", usec); + RESET_COUNTERS(); + return; + } + sum += usec; ++cnt; + if (!(cnt % 25)) { + printf("%10lld %10lld %10d\n", img->vpts - last_vpts, vpts - abs_vpts, sum); + RESET_COUNTERS(); + } +} +#endif + static void overlay_and_display_frame (vos_t *this, vo_frame_t *img, int64_t vpts) { xine_stream_t *stream; @@ -1033,6 +1092,9 @@ vo_frame_inc_lock( img ); this->last_frame = img; +#ifdef SHOW_FRAME_DEBUG + debug_frame_timing(img, vpts); +#endif this->driver->display_frame (this->driver, img); /* @@ -1231,10 +1293,15 @@ usec_to_sleep = 1000; next_frame_vpts = vpts; /* wait only once */ } - +/* + * The patch causes frame update intervals sent to the + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. + */ +#if 0 /* limit usec_to_sleep to maintain responsiveness */ if (usec_to_sleep > MAX_USEC_TO_SLEEP) usec_to_sleep = MAX_USEC_TO_SLEEP; +#endif lprintf ("%" PRId64 " usec to sleep at master vpts %" PRId64 "\n", usec_to_sleep, vpts); diff -r ef6480bf3839 -r e7bcf392d58c src/xine-utils/utils.c --- a/src/xine-utils/utils.c Tue May 19 15:43:53 2009 +0100 +++ b/src/xine-utils/utils.c Wed May 20 09:16:53 2009 +0200 @@ -456,6 +456,11 @@ * a thread-safe usecond sleep */ void xine_usec_sleep(unsigned usec) { +/* + * The patch causes frame update intervals sent to the + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. + */ +#if 0 /* prefer usleep */ #ifdef WIN32 /* select does not work on win32 */ Sleep(usec / 1000); @@ -481,6 +486,9 @@ select(0, 0, 0, 0, &tm); # endif #endif +#else + usleep(usec); +#endif } [frc.patch] # HG changeset patch # User Paul Menzel <paulepanter@...> # Date 1242803813 -7200 # Node ID e7bcf392d58c914a91b718ecc739f095fcb2cdb2 # Parent ef6480bf38399c3bc832e554eca1311ddd4385e6 Frame Rate Control patches from Thomas Hilber. diff -r ef6480bf3839 -r e7bcf392d58c src/xine-engine/video_out.c --- a/src/xine-engine/video_out.c Tue May 19 15:43:53 2009 +0100 +++ b/src/xine-engine/video_out.c Wed May 20 09:16:53 2009 +0200 @@ -997,6 +997,65 @@ } } +#define SHOW_FRAME_DEBUG + +#ifdef SHOW_FRAME_DEBUG + +#define MIDDLE 40000 +#define CATCH 10000 + +#define VSF_SUB(a, b, c) \ + if ((a).tv_usec < (b).tv_usec) { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ + } else { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec; \ + } + +#define VSF_TV2USEC(a, b) \ + (b) = (a).tv_sec * 1000000 + (a).tv_usec; + +#define RESET_COUNTERS() \ + cnt = 0; \ + sum = 0; \ + abs_vpts = vpts; \ + last_vpts = img->vpts; + +void +debug_frame_timing(img, vpts) + vo_frame_t *img; + int64_t vpts; +{ + static int sum; + static int cnt; + static int64_t abs_vpts; + static int64_t last_vpts; + static struct timeval t_prev; + + int usec; + struct timeval t; + struct timeval t_now; + + gettimeofday(&t_now, 0); + VSF_SUB(t_now, t_prev, t); + VSF_TV2USEC(t, usec); + t_prev = t_now; + + if (usec < MIDDLE - CATCH + || usec > MIDDLE + CATCH ) { + if (last_vpts) printf("STRAY: %10d\n", usec); + RESET_COUNTERS(); + return; + } + sum += usec; ++cnt; + if (!(cnt % 25)) { + printf("%10lld %10lld %10d\n", img->vpts - last_vpts, vpts - abs_vpts, sum); + RESET_COUNTERS(); + } +} +#endif + static void overlay_and_display_frame (vos_t *this, vo_frame_t *img, int64_t vpts) { xine_stream_t *stream; @@ -1033,6 +1092,9 @@ vo_frame_inc_lock( img ); this->last_frame = img; +#ifdef SHOW_FRAME_DEBUG + debug_frame_timing(img, vpts); +#endif this->driver->display_frame (this->driver, img); /* @@ -1231,10 +1293,15 @@ usec_to_sleep = 1000; next_frame_vpts = vpts; /* wait only once */ } - +/* + * The patch causes frame update intervals sent to the + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. + */ +#if 0 /* limit usec_to_sleep to maintain responsiveness */ if (usec_to_sleep > MAX_USEC_TO_SLEEP) usec_to_sleep = MAX_USEC_TO_SLEEP; +#endif lprintf ("%" PRId64 " usec to sleep at master vpts %" PRId64 "\n", usec_to_sleep, vpts); diff -r ef6480bf3839 -r e7bcf392d58c src/xine-utils/utils.c --- a/src/xine-utils/utils.c Tue May 19 15:43:53 2009 +0100 +++ b/src/xine-utils/utils.c Wed May 20 09:16:53 2009 +0200 @@ -456,6 +456,11 @@ * a thread-safe usecond sleep */ void xine_usec_sleep(unsigned usec) { +/* + * The patch causes frame update intervals sent to the + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. + */ +#if 0 /* prefer usleep */ #ifdef WIN32 /* select does not work on win32 */ Sleep(usec / 1000); @@ -481,6 +486,9 @@ select(0, 0, 0, 0, &tm); # endif #endif +#else + usleep(usec); +#endif } ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://www.creativitycat.com _______________________________________________ xine-devel mailing list xine-devel@... https://lists.sourceforge.net/lists/listinfo/xine-devel |
|
|
Re: [RFC] [PATCH] evenly spaced update intervalsOn Thu, 21 May 2009, Paul Menzel wrote:
> The patch causes frame update intervals sent to the > Xserver much more evenly spaced. Which allows the soft-PLL to lock > earlier. > In combination with other frame rate control patches [1], this enables > the user for example to watch a video on a TV set with a > VGA-2-SCART-adapter. > > > [1] http://frc.easy-vdr.de/ First of all I must applaud you for your pioneering work. This is _the_work_ that will make linux video great :) Have you considered working with xorg people to get it included into currently evolving VAAPI or equivalent? There is definitely a need for such in future video acceleration API. I've been making some noise about framelocking here: http://www.botchco.com/agd5f/?p=15#comment-1004 and also on TVtime bugtracker or thereabouts. I havent yet tested anything, but will do as soon as time permits. Anyway, this is just great. -Vesa ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ xine-devel mailing list xine-devel@... https://lists.sourceforge.net/lists/listinfo/xine-devel |
|
|
Re: [RFC] [PATCH] evenly spaced update intervalsDear list,
Am Donnerstag, den 21.05.2009, 00:26 +0200 schrieb Paul Menzel: > The patch causes frame update intervals sent to the > Xserver much more evenly spaced. Which allows the soft-PLL to lock > earlier. > > In combination with other frame rate control patches [1], this enables > the user for example to watch a video on a TV set with a > VGA-2-SCART-adapter. > > > [1] http://frc.easy-vdr.de/ > > > Signed-off-by: Thomas Hilber <sparkie@...> > Signed-off-by: Paul Menzel <paulepanter@...> busy, this is the wrong list or if something else is wrong. The patch is just a read for correction. Could someone else test it already. How do you want us to proceed with those ifdefs? Is it beneficial to create configuration options for this? If yes, where should we put those? Any pointers please and also please suggestions for the names of those options? Thanks, Paul > # HG changeset patch > # User Paul Menzel <paulepanter@...> > # Date 1242803813 -7200 > # Node ID e7bcf392d58c914a91b718ecc739f095fcb2cdb2 > # Parent ef6480bf38399c3bc832e554eca1311ddd4385e6 > Frame Rate Control patches from Thomas Hilber. > > diff -r ef6480bf3839 -r e7bcf392d58c src/xine-engine/video_out.c > --- a/src/xine-engine/video_out.c Tue May 19 15:43:53 2009 +0100 > +++ b/src/xine-engine/video_out.c Wed May 20 09:16:53 2009 +0200 > @@ -997,6 +997,65 @@ > } > } > > +#define SHOW_FRAME_DEBUG > + > +#ifdef SHOW_FRAME_DEBUG > + > +#define MIDDLE 40000 > +#define CATCH 10000 > + > +#define VSF_SUB(a, b, c) \ > + if ((a).tv_usec < (b).tv_usec) { \ > + (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ > + (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ > + } else { \ > + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ > + (c).tv_usec = (a).tv_usec - (b).tv_usec; \ > + } > + > +#define VSF_TV2USEC(a, b) \ > + (b) = (a).tv_sec * 1000000 + (a).tv_usec; > + > +#define RESET_COUNTERS() \ > + cnt = 0; \ > + sum = 0; \ > + abs_vpts = vpts; \ > + last_vpts = img->vpts; > + > +void > +debug_frame_timing(img, vpts) > + vo_frame_t *img; > + int64_t vpts; > +{ > + static int sum; > + static int cnt; > + static int64_t abs_vpts; > + static int64_t last_vpts; > + static struct timeval t_prev; > + > + int usec; > + struct timeval t; > + struct timeval t_now; > + > + gettimeofday(&t_now, 0); > + VSF_SUB(t_now, t_prev, t); > + VSF_TV2USEC(t, usec); > + t_prev = t_now; > + > + if (usec < MIDDLE - CATCH > + || usec > MIDDLE + CATCH ) { > + if (last_vpts) printf("STRAY: %10d\n", usec); > + RESET_COUNTERS(); > + return; > + } > + sum += usec; ++cnt; > + if (!(cnt % 25)) { > + printf("%10lld %10lld %10d\n", img->vpts - last_vpts, vpts - abs_vpts, sum); > + RESET_COUNTERS(); > + } > +} > +#endif > + > static void overlay_and_display_frame (vos_t *this, > vo_frame_t *img, int64_t vpts) { > xine_stream_t *stream; > @@ -1033,6 +1092,9 @@ > vo_frame_inc_lock( img ); > this->last_frame = img; > > +#ifdef SHOW_FRAME_DEBUG > + debug_frame_timing(img, vpts); > +#endif > this->driver->display_frame (this->driver, img); > > /* > @@ -1231,10 +1293,15 @@ > usec_to_sleep = 1000; > next_frame_vpts = vpts; /* wait only once */ > } > - > +/* > + * The patch causes frame update intervals sent to the > + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. > + */ > +#if 0 > /* limit usec_to_sleep to maintain responsiveness */ > if (usec_to_sleep > MAX_USEC_TO_SLEEP) > usec_to_sleep = MAX_USEC_TO_SLEEP; > +#endif > > lprintf ("%" PRId64 " usec to sleep at master vpts %" PRId64 "\n", usec_to_sleep, vpts); > > diff -r ef6480bf3839 -r e7bcf392d58c src/xine-utils/utils.c > --- a/src/xine-utils/utils.c Tue May 19 15:43:53 2009 +0100 > +++ b/src/xine-utils/utils.c Wed May 20 09:16:53 2009 +0200 > @@ -456,6 +456,11 @@ > * a thread-safe usecond sleep > */ > void xine_usec_sleep(unsigned usec) { > +/* > + * The patch causes frame update intervals sent to the > + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. > + */ > +#if 0 /* prefer usleep */ > #ifdef WIN32 > /* select does not work on win32 */ > Sleep(usec / 1000); > @@ -481,6 +486,9 @@ > select(0, 0, 0, 0, &tm); > # endif > #endif > +#else > + usleep(usec); > +#endif > } > > > ------------------------------------------------------------------------------ > Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT > is a gathering of tech-side developers & brand creativity professionals. Meet > the minds behind Google Creative Lab, Visual Complexity, Processing, & > iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian > Group, R/GA, & Big Spaceship. http://www.creativitycat.com > _______________________________________________ xine-devel mailing list xine-devel@... https://lists.sourceforge.net/lists/listinfo/xine-devel ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ xine-devel mailing list xine-devel@... https://lists.sourceforge.net/lists/listinfo/xine-devel |
|
|
How can patches be submitted? (was: Re: [RFC] [PATCH] evenly spaced update intervals)Dear xine developers,
sorry for getting on your nerves. But unfortunately there has not been a reply to the patch in the last week and only one other mail was sent to this list since I subscribed. Is there somewhere else we should go to get in contact with you guys? Is xine development still happening? It would be nice and fair to have this information (or please point me to the information on the WWW) so that the developers of my project I am involved in can decide how to go on/proceed. Bests, Paul ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ xine-devel mailing list xine-devel@... https://lists.sourceforge.net/lists/listinfo/xine-devel |
|
|
Re: [RFC] [PATCH] evenly spaced update intervalsDear list,
Am Mittwoch, den 27.05.2009, 10:16 +0200 schrieb Paul Menzel: > Am Donnerstag, den 21.05.2009, 00:26 +0200 schrieb Paul Menzel: > > The patch causes frame update intervals sent to the > > Xserver much more evenly spaced. Which allows the soft-PLL to lock > > earlier. > > > > In combination with other frame rate control patches [1], this enables > > the user for example to watch a video on a TV set with a > > VGA-2-SCART-adapter. > > > > > > [1] http://frc.easy-vdr.de/ > > > > > > Signed-off-by: Thomas Hilber <sparkie@...> > > Signed-off-by: Paul Menzel <paulepanter@...> > > there has not been a reply yet to the list, so I wonder if everyone is > busy, this is the wrong list or if something else is wrong. > > The patch is just a read for correction. Could someone else test it > already. that I can take an excerpt from the conversation and quote it on this list. > > # HG changeset patch > > # User Paul Menzel <paulepanter@...> > > # Date 1242803813 -7200 > > # Node ID e7bcf392d58c914a91b718ecc739f095fcb2cdb2 > > # Parent ef6480bf38399c3bc832e554eca1311ddd4385e6 > > Frame Rate Control patches from Thomas Hilber. > > > > diff -r ef6480bf3839 -r e7bcf392d58c src/xine-engine/video_out.c > > --- a/src/xine-engine/video_out.c Tue May 19 15:43:53 2009 +0100 > > +++ b/src/xine-engine/video_out.c Wed May 20 09:16:53 2009 +0200 > > @@ -997,6 +997,65 @@ > > } > > } > > > > +#define SHOW_FRAME_DEBUG > > + > > +#ifdef SHOW_FRAME_DEBUG > > + > > +#define MIDDLE 40000 > > +#define CATCH 10000 > > + > > +#define VSF_SUB(a, b, c) \ > > + if ((a).tv_usec < (b).tv_usec) { \ > > + (c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \ > > + (c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \ > > + } else { \ > > + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ > > + (c).tv_usec = (a).tv_usec - (b).tv_usec; \ > > + } > > + > > +#define VSF_TV2USEC(a, b) \ > > + (b) = (a).tv_sec * 1000000 + (a).tv_usec; > > + > > +#define RESET_COUNTERS() \ > > + cnt = 0; \ > > + sum = 0; \ > > + abs_vpts = vpts; \ > > + last_vpts = img->vpts; > > + > > +void > > +debug_frame_timing(img, vpts) > > + vo_frame_t *img; > > + int64_t vpts; > > +{ > > + static int sum; > > + static int cnt; > > + static int64_t abs_vpts; > > + static int64_t last_vpts; > > + static struct timeval t_prev; > > + > > + int usec; > > + struct timeval t; > > + struct timeval t_now; > > + > > + gettimeofday(&t_now, 0); > > + VSF_SUB(t_now, t_prev, t); > > + VSF_TV2USEC(t, usec); > > + t_prev = t_now; > > + > > + if (usec < MIDDLE - CATCH > > + || usec > MIDDLE + CATCH ) { > > + if (last_vpts) printf("STRAY: %10d\n", usec); > > + RESET_COUNTERS(); > > + return; > > + } > > + sum += usec; ++cnt; > > + if (!(cnt % 25)) { > > + printf("%10lld %10lld %10d\n", img->vpts - last_vpts, vpts - abs_vpts, sum); > > + RESET_COUNTERS(); > > + } > > +} > > +#endif > > + > > static void overlay_and_display_frame (vos_t *this, > > vo_frame_t *img, int64_t vpts) { > > xine_stream_t *stream; > > @@ -1033,6 +1092,9 @@ > > vo_frame_inc_lock( img ); > > this->last_frame = img; > > > > +#ifdef SHOW_FRAME_DEBUG > > + debug_frame_timing(img, vpts); > > +#endif > > this->driver->display_frame (this->driver, img); > > > > /* > > @@ -1231,10 +1293,15 @@ > > usec_to_sleep = 1000; > > next_frame_vpts = vpts; /* wait only once */ > > } > > - > > +/* > > + * The patch causes frame update intervals sent to the > > + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. > > + */ > > +#if 0 > > /* limit usec_to_sleep to maintain responsiveness */ > > if (usec_to_sleep > MAX_USEC_TO_SLEEP) > > usec_to_sleep = MAX_USEC_TO_SLEEP; > > +#endif 22:51 < rnissl> consider slow motion replay and frame durations > 3600 pts 22:51 < rnissl> any OSD operation will be blocked for that time > > > > lprintf ("%" PRId64 " usec to sleep at master vpts %" PRId64 "\n", usec_to_sleep, vpts); > > > > diff -r ef6480bf3839 -r e7bcf392d58c src/xine-utils/utils.c > > --- a/src/xine-utils/utils.c Tue May 19 15:43:53 2009 +0100 > > +++ b/src/xine-utils/utils.c Wed May 20 09:16:53 2009 +0200 > > @@ -456,6 +456,11 @@ > > * a thread-safe usecond sleep > > */ > > void xine_usec_sleep(unsigned usec) { > > +/* > > + * The patch causes frame update intervals sent to the > > + * Xserver much more evenly spaced. Which allows the soft-PLL to lock earlier. > > + */ > > +#if 0 /* prefer usleep */ > > #ifdef WIN32 > > /* select does not work on win32 */ > > Sleep(usec / 1000); > > @@ -481,6 +486,9 @@ > > select(0, 0, 0, 0, &tm); > > # endif > > #endif > > +#else > > + usleep(usec); > > +#endif > > } 22:52 < PaulePanter> rnissl: But I will forward your review to him. 22:53 < rnissl> xine-lib originally used nano_sleep() which is still part of those define construct 22:53 < rnissl> recently, it was changed to select() as it allows the cpu to stay longer in lower power mode 22:54 < rnissl> I'm not sure whether the different api call is really responsible for that 22:54 < rnissl> most likely it's simply the fact that any sleep will be rounded up to at least 10 ms 22:55 < rnissl> so maybe that's the actuall problem 22:55 < PaulePanter> rnissl: Thank you for those insights. Thanks goes again to Reinhard. Bests, Paul ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ xine-devel mailing list xine-devel@... https://lists.sourceforge.net/lists/listinfo/xine-devel |
| Free embeddable forum powered by Nabble | Forum Help |