Index: Makefile =================================================================== RCS file: /home/pcvs/ports/multimedia/libxine/Makefile,v retrieving revision 1.163 diff -u -p -r1.163 Makefile --- Makefile 14 Sep 2010 18:58:49 -0000 1.163 +++ Makefile 14 Jan 2011 00:12:36 -0000 @@ -76,7 +76,8 @@ OPTIONS= ARTS "Enable aRts support" off AALIB "Enable aalib support" off \ IMAGEMAGICK "Enable ImageMagick support" off \ GTK2 "Enable gdkpixbuf support" off \ - WAVPACK "Enable WavPack support" off + WAVPACK "Enable WavPack support" off \ + VDPAU "Enable VDPAU support patches" off MAN1= xine-config.1 xine-list-1.1.1 MAN5= xine.5 @@ -202,6 +203,14 @@ PLIST_SUB+= WITH_WAVPACK="@comment " CONFIGURE_ARGS+= --without-wavpack .endif +.if defined(WITH_VDPAU) +USE_AUTOTOOLS= autoconf +LIB_DEPENDS+= vdpau.1:${PORTSDIR}/multimedia/libvdpau +PLIST_SUB+= VDPAU="" +.else +PLIST_SUB+= VDPAU="@comment " +.endif + .if ${CONFIGURE_ARGS:M*--without-imagemagick*} == "" || ${CONFIGURE_ARGS:M*-disable-gdkpixbuf*} == "" PLIST_SUB+= WITH_DMX_IMAGE="" .else @@ -216,6 +225,11 @@ CONFIGURE_ARGS+= --disable-vidix .endif post-patch: +.if defined(WITH_VDPAU) + for i in `${LS} ${FILESDIR}/post-patch-vdpau* |${SED} /.orig$$/d`; do \ + ${PATCH} -d ${WRKSRC} -p1 --forward --quiet <$$i ;\ + done +.endif .for f in libtool ltmain.sh @${REINPLACE_CMD} -e \ '/freebsd-elf)/,/;;/ s|major="\.$$current"|major=.`expr $$current - $$age`|; \ Index: distinfo =================================================================== RCS file: /home/pcvs/ports/multimedia/libxine/distinfo,v retrieving revision 1.42 diff -u -p -r1.42 distinfo --- distinfo 18 Aug 2010 19:10:55 -0000 1.42 +++ distinfo 10 Jan 2011 20:38:27 -0000 @@ -1,3 +1,4 @@ -MD5 (xine-lib-1.1.19.tar.xz) = d0969c067dc32f33c5ea431e5e2106ce SHA256 (xine-lib-1.1.19.tar.xz) = f834f646880bb44186018d12280ac27c8314447de9335b6fe390157b26df9cd9 SIZE (xine-lib-1.1.19.tar.xz) = 5782580 +SHA256 (xine-lib_1.1.19-2.etobi2.debian.tar.gz) = 41d2ff49284973690914dd8fea0ec25cbbc2a6b60d391bdefe8fab5335eca6b7 +SIZE (xine-lib_1.1.19-2.etobi2.debian.tar.gz) = 179402 Index: pkg-plist =================================================================== RCS file: /home/pcvs/ports/multimedia/libxine/pkg-plist,v retrieving revision 1.56 diff -u -p -r1.56 pkg-plist --- pkg-plist 18 Aug 2010 19:10:55 -0000 1.56 +++ pkg-plist 12 Jan 2011 22:08:48 -0000 @@ -227,12 +227,19 @@ share/aclocal/xine.m4 %%DATADIR%%/libxine1/fonts/serif-32.xinefont.gz %%DATADIR%%/libxine1/fonts/serif-48.xinefont.gz %%DATADIR%%/libxine1/fonts/serif-64.xinefont.gz +%%VDPAU%%include/xine/vdr.h +%%VDPAU%%%%PLUGINSDIR%%/xineplug_vo_out_vdpau.so +%%VDPAU%%%%PLUGINSDIR%%/xineplug_dmx_vc1_es.so +%%VDPAU%%%%PLUGINSDIR%%/xineplug_decode_vdpau_h264.so +%%VDPAU%%%%PLUGINSDIR%%/xineplug_decode_vdpau_mpeg12.so +%%VDPAU%%%%PLUGINSDIR%%/xineplug_decode_vdpau_vc1.so +%%VDPAU%%%%PLUGINSDIR%%/xineplug_vdr.so @dirrm include/xine @dirrm %%PLUGINSDIR%%/vidix @dirrm %%PLUGINSDIR%%/post -@dirrm %%PLUGINSDIR%% -@dirrm lib/xine/plugins -@dirrm lib/xine +@dirrmtry %%PLUGINSDIR%% +@dirrmtry lib/xine/plugins +@dirrmtry lib/xine @dirrm %%DOCSDIR%%/hackersguide @dirrm %%DOCSDIR%% %%NLS%%@dirrmtry share/locale/pl_PL/LC_MESSAGES @@ -241,4 +248,4 @@ share/aclocal/xine.m4 %%NLS%%@dirrmtry share/locale/en_US @dirrm %%DATADIR%%/libxine1/fonts @dirrm %%DATADIR%%/libxine1 -@dirrm %%DATADIR%% +@dirrmtry %%DATADIR%% Index: files/post-patch-vdpau @@ -0,0 +1,17742 @@ +Origin: upstream, other, * +Description: Applied patches. See Vcs-* headers in debian/control. + +--- /dev/null ++++ xine-lib-1.1.19/README-VDPAU +@@ -0,0 +1,70 @@ ++xine-vdpau README: ++------------------------------------------------------------------------------ ++ ++So, you want to give it a try, but wonder which steps are required. ++Ok, so here it is: ++ ++0) you need nvidia's driver 180.22 or later. ++ ++1) get the sources: ++svn co svn://jusst.de/xine-vdpau ++ ++2) compile the sources: ++cd xine-vdpau ++./autogen.sh ++./configure ++make ++make install (as root) ++ **(make sure that no other xine-lib installation will conflict with this one) ++ ++3) edit your xine configuration ++nano $HOME/.xine/config (if it does not exist, first run "xine --no-logo" then quit. ++search for "engine.buffers.video_num_frames" and set it to 22 ++ ++4) running the beast: ++xine -verbose /path/to/a/working/sample ++ ** --verbose will print some usefull things in your console (in case of problems, ++ the developers will ask you to give this output, at least) ++ ++5) update your svn copy quite often ++ ++6) don't blame us if it crashes, burn you gpu (unlikely:) or anything else. ++ ++ ++------------------------------------------------------------------------------ ++ ++FAQ: ++ ++Q: ++ Why my file plays fine with mplayer-vdpau and not with xine-vdpau? ++A: ++ We are not using the nvidia's libavcodec patch. ++ We are writing decoders from scratch. ++ So don't expect them to be as mature as ffmpeg ones. Not yet. ++ ++Q: ++ Why mpeg2 doesn't use less cpu than software decoder? ++A: ++ Because at that moment it does a lot of memcpy. This will be fixed soon, but that's not ++ a priority. Stability is our focus. ++ ++Q: ++ Is deinterlacing working? ++A: ++ Yes. It's already quite good (doing 50i->50p), but could even be better in the future. ++ ++Q: ++ How do i get it working with VDR, Kaffeine, whatever. ++A: ++ Ask VDR, Kaffeine, whatever developers. ++ (Note: for kaffeine you are lucky, i'm going to tell you the tip. ++ Build kaffeine like that: ./configure --without-xcb && make && make install) ++ ++Q: ++ How can i contact you? ++A: ++ IRC: #xine-vdpau on freenode ++ MAIL: http://lists.kafic.ba/mailman/listinfo/xine-vdpau ++ Eventually, nvnews. ++ ++---------------------------------------------------------------------------- +--- xine-lib-1.1.19.orig/configure.ac ++++ xine-lib-1.1.19/configure.ac +@@ -913,6 +913,20 @@ AC_SUBST(XVMC_LIBS) + + + dnl --------------------------------------------- ++dnl Check for VDPAU ++dnl --------------------------------------------- ++AC_ARG_WITH([vdpau], AS_HELP_STRING([--without-vdpau], [Doesn't build VDPAU plugins])) ++if test "x$with_vdpau" != "xno"; then ++ AC_CHECK_HEADERS([vdpau/vdpau_x11.h], [have_vdpau=yes], [have_vdpau=no]) ++ if test "x$have_vdpau" = "xyes"; then ++ AC_CHECK_LIB(vdpau, vdp_device_create_x11, have_vdpau="yes", [have_vdpau="no"], [$X_LIBS $X_PRE_LIBS -lXext $X_EXTRA_LIBS]) ++ fi ++fi ++ ++AM_CONDITIONAL(HAVE_VDPAU, test "x$have_vdpau" = "xyes" ) ++ ++ ++dnl --------------------------------------------- + dnl Check for xcb + dnl --------------------------------------------- + AC_ARG_WITH([xcb], AS_HELP_STRING([--without-xcb], [Doesn't build XCB video out plugins])) +@@ -2811,6 +2836,7 @@ src/libmpeg2new/libmpeg2/Makefile + src/libmpeg2new/include/Makefile + src/libmusepack/Makefile + src/libmusepack/musepack/Makefile ++src/libvdpau/Makefile + src/libspudec/Makefile + src/libspucc/Makefile + src/libspucmml/Makefile +@@ -2847,6 +2873,7 @@ src/video_out/vidix/Makefile + src/video_out/vidix/drivers/Makefile + src/xine-utils/Makefile + src/xine-engine/Makefile ++src/vdr/Makefile + win32/Makefile + win32/include/Makefile]) + AC_CONFIG_COMMANDS([default],[[chmod +x ./misc/SlackBuild ./misc/build_rpms.sh ./misc/relchk.sh]],[[]]) +@@ -2889,6 +2916,7 @@ echo " - file - net" + echo " - stdin_fifo - rtp" + echo " - http - mms" + echo " - pnm - rtsp" ++echo " - vdr" + if test "$have_supported_dvb" = yes; then + echo " - dvb" + fi +@@ -3102,6 +3130,7 @@ echo " - invert - expand" + echo " - eq - eq2" + echo " - boxblur - denoise3d" + echo " - unsharp - tvtime" ++echo " - vdr" + echo " * SFX:" + echo " - goom - oscope" + echo " - fftscope - mosaico" +@@ -3156,6 +3185,9 @@ if test "x$have_xcb" = "xyes"; then + echo " - xcb-xv (XVideo using XCB)" + fi + fi ++if test "x$have_vdpau" = "xyes"; then ++ echo " - vdpau (X11 VDPAU)" ++fi + if test "x$no_aalib" != "xyes"; then + echo " - aa (Ascii ART)" + fi +fi +--- xine-lib-1.1.19.orig/src/Makefile.am ++++ xine-lib-1.1.19/src/Makefile.am +@@ -27,5 +27,7 @@ SUBDIRS = \ + libreal \ + libfaad \ + libmusepack \ ++ libvdpau \ + post \ +- combined ++ combined \ ++ vdr +--- xine-lib-1.1.19.orig/src/Makefile.in ++++ xine-lib-1.1.19/src/Makefile.in +@@ -453,8 +459,10 @@ SUBDIRS = \ + libreal \ + libfaad \ + libmusepack \ ++ libvdpau \ + post \ +- combined ++ combined \ ++ vdr + + all: all-recursive + +--- xine-lib-1.1.19.orig/src/xine-engine/post.h ++++ xine-lib-1.1.19/src/xine-engine/post.h +@@ -177,6 +177,13 @@ struct post_video_port_s { + /* the new frame function pointers */ + vo_frame_t *new_frame; + ++ /* if you want to decide yourself, whether the preprocessing functions ++ * should still be routed when draw is intercepted, fill in this ++ * function; _x_post_intercept_video_frame() acts as a template method ++ * and asks your function; return a boolean; the default is _not_ to ++ * route preprocessing functions when draw is intercepted */ ++ int (*route_preprocessing_procs)(post_video_port_t *self, vo_frame_t *frame); ++ + /* if you want to decide yourself, whether the overlay manager should + * be intercepted, fill in this function; get_overlay_manager() acts as + * a template method and asks your function; return a boolean; +--- xine-lib-1.1.19.orig/src/xine-engine/osd.c ++++ xine-lib-1.1.19/src/xine-engine/osd.c +@@ -157,14 +157,23 @@ static osd_object_t *XINE_MALLOC osd_new + osd->next = this->osds; + this->osds = osd; + ++ osd->video_window_x = 0; ++ osd->video_window_y = 0; ++ osd->video_window_width = 0; ++ osd->video_window_height = 0; ++ osd->extent_width = 0; ++ osd->extent_height = 0; + osd->width = width; + osd->height = height; + osd->area = calloc(width, height); ++ osd->area_touched = 0; + +- osd->x1 = width; +- osd->y1 = height; +- osd->x2 = 0; +- osd->y2 = 0; ++ osd->x1 = osd->argb_layer.x1 = width; ++ osd->y1 = osd->argb_layer.y1 = height; ++ osd->x2 = osd->argb_layer.x2 = 0; ++ osd->y2 = osd->argb_layer.y2 = 0; ++ ++ pthread_mutex_init(&osd->argb_layer.mutex, NULL); + + memcpy(osd->color, textpalettes_color[0], sizeof(textpalettes_color[0])); + memcpy(osd->trans, textpalettes_trans[0], sizeof(textpalettes_trans[0])); +@@ -183,6 +192,31 @@ static osd_object_t *XINE_MALLOC osd_new + return osd; + } + ++/* ++ * osd extent must be set to achive video resolution independent osds ++ * both sizes must be > 0 to take effect. otherwise, video resolution ++ * will still be used. the extent defines the reference coordinate ++ * system which is matched to the video output area. ++ */ ++static void osd_set_extent (osd_object_t *osd, int extent_width, int extent_height) { ++ ++ osd->extent_width = extent_width; ++ osd->extent_height = extent_height; ++} ++ ++/* ++ * osd video window defines an area withing osd extent where the ++ * video shall be scaled to while an osd is displayed on screen. ++ * both width and height must be > 0 to take effect. ++ */ ++static void osd_set_video_window (osd_object_t *osd, int window_x, int window_y, int window_width, int window_height) { ++ ++ osd->video_window_x = window_x; ++ osd->video_window_y = window_y; ++ osd->video_window_width = window_width; ++ osd->video_window_height = window_height; ++} ++ + + + /* +@@ -242,12 +276,23 @@ static int _osd_show (osd_object_t *osd, + this->event.object.handle = osd->handle; + + memset( this->event.object.overlay, 0, sizeof(*this->event.object.overlay) ); ++ ++ this->event.object.overlay->argb_layer = &osd->argb_layer; ++ + this->event.object.overlay->unscaled = unscaled; + this->event.object.overlay->x = osd->display_x + osd->x1; + this->event.object.overlay->y = osd->display_y + osd->y1; + this->event.object.overlay->width = osd->x2 - osd->x1; + this->event.object.overlay->height = osd->y2 - osd->y1; + ++ this->event.object.overlay->video_window_x = osd->video_window_x; ++ this->event.object.overlay->video_window_y = osd->video_window_y; ++ this->event.object.overlay->video_window_width = osd->video_window_width; ++ this->event.object.overlay->video_window_height = osd->video_window_height; ++ ++ this->event.object.overlay->extent_width = osd->extent_width; ++ this->event.object.overlay->extent_height = osd->extent_height; ++ + this->event.object.overlay->hili_top = 0; + this->event.object.overlay->hili_bottom = this->event.object.overlay->height; + this->event.object.overlay->hili_left = 0; +@@ -255,53 +300,59 @@ static int _osd_show (osd_object_t *osd, + + /* there will be at least that many rle objects (one for each row) */ + this->event.object.overlay->num_rle = 0; +- /* We will never need more rle objects than columns in any row +- Rely on lazy page allocation to avoid us actually taking up +- this much RAM */ +- this->event.object.overlay->data_size = osd->width * osd->height; +- rle_p = this->event.object.overlay->rle = +- malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) ); ++ if (!osd->area_touched) { ++ /* avoid rle encoding when only argb_layer is modified */ ++ this->event.object.overlay->data_size = 0; ++ rle_p = this->event.object.overlay->rle = NULL; ++ } else { ++ /* We will never need more rle objects than columns in any row ++ Rely on lazy page allocation to avoid us actually taking up ++ this much RAM */ ++ this->event.object.overlay->data_size = osd->width * osd->height; ++ rle_p = this->event.object.overlay->rle = ++ malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) ); + +- for( y = osd->y1; y < osd->y2; y++ ) { ++ for( y = osd->y1; y < osd->y2; y++ ) { + #ifdef DEBUG_RLE +- lprintf("osd_show %p y = %d: ", osd, y); ++ lprintf("osd_show %p y = %d: ", osd, y); + #endif +- c = osd->area + y * osd->width + osd->x1; ++ c = osd->area + y * osd->width + osd->x1; + +- /* initialize a rle object with the first pixel's color */ +- rle.len = 1; +- rle.color = *c++; ++ /* initialize a rle object with the first pixel's color */ ++ rle.len = 1; ++ rle.color = *c++; + +- /* loop over the remaining pixels in the row */ +- for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) { +- if( rle.color != *c ) { ++ /* loop over the remaining pixels in the row */ ++ for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) { ++ if( rle.color != *c ) { + #ifdef DEBUG_RLE +- lprintf("(%d, %d), ", rle.len, rle.color); ++ lprintf("(%d, %d), ", rle.len, rle.color); + #endif +- *rle_p++ = rle; +- this->event.object.overlay->num_rle++; ++ *rle_p++ = rle; ++ this->event.object.overlay->num_rle++; + +- rle.color = *c; +- rle.len = 1; +- } else { +- rle.len++; ++ rle.color = *c; ++ rle.len = 1; ++ } else { ++ rle.len++; ++ } + } +- } + #ifdef DEBUG_RLE +- lprintf("(%d, %d)\n", rle.len, rle.color); ++ lprintf("(%d, %d)\n", rle.len, rle.color); + #endif +- *rle_p++ = rle; +- this->event.object.overlay->num_rle++; +- } ++ *rle_p++ = rle; ++ this->event.object.overlay->num_rle++; ++ } + #ifdef DEBUG_RLE +- lprintf("osd_show %p rle ends\n", osd); ++ lprintf("osd_show %p rle ends\n", osd); + #endif +- lprintf("num_rle = %d\n", this->event.object.overlay->num_rle); ++ lprintf("num_rle = %d\n", this->event.object.overlay->num_rle); + +- memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); +- memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); +- memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); +- memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); ++ memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); ++ memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); ++ memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); ++ memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); ++ } + + this->event.event_type = OVERLAY_EVENT_SHOW; + this->event.vpts = vpts; +@@ -385,11 +436,14 @@ static int osd_hide (osd_object_t *osd, + static void osd_clear (osd_object_t *osd) { + lprintf("osd=%p\n",osd); + +- memset(osd->area, 0, osd->width * osd->height); +- osd->x1 = osd->width; +- osd->y1 = osd->height; +- osd->x2 = 0; +- osd->y2 = 0; ++ if (osd->area_touched) { ++ osd->area_touched = 0; ++ memset(osd->area, 0, osd->width * osd->height); ++ } ++ osd->x1 = osd->argb_layer.x1 = osd->width; ++ osd->y1 = osd->argb_layer.y1 = osd->height; ++ osd->x2 = osd->argb_layer.x2 = 0; ++ osd->y2 = osd->argb_layer.y2 = 0; + } + + /* +@@ -411,6 +465,7 @@ static void osd_point (osd_object_t *osd + osd->x2 = MAX(osd->x2, (x + 1)); + osd->y1 = MIN(osd->y1, y); + osd->y2 = MAX(osd->y2, (y + 1)); ++ osd->area_touched = 1; + + c = osd->area + y * osd->width + x; + *c = color; +@@ -470,6 +525,7 @@ static void osd_line (osd_object_t *osd, + osd->x2 = MAX( osd->x2, x2 ); + osd->y1 = MIN( osd->y1, y1 ); + osd->y2 = MAX( osd->y2, y2 ); ++ osd->area_touched = 1; + + dx = x2 - x1; + dy = y2 - y1; +@@ -583,6 +639,7 @@ static void osd_filled_rect (osd_object_ + osd->x2 = MAX( osd->x2, dx ); + osd->y1 = MIN( osd->y1, y ); + osd->y2 = MAX( osd->y2, dy ); ++ osd->area_touched = 1; + + dx -= x; + dy -= y; +@@ -1143,6 +1200,7 @@ static int osd_render_text (osd_object_t + + if( x1 < osd->x1 ) osd->x1 = x1; + if( y1 < osd->y1 ) osd->y1 = y1; ++ osd->area_touched = 1; + + inbuf = text; + inbytesleft = strlen(text); +@@ -1483,6 +1541,7 @@ static void osd_free_object (osd_object_ + else + this->osds = osd->next; + ++ pthread_mutex_destroy(&osd->argb_layer.mutex); + free( osd ); + break; + } +@@ -1528,6 +1587,7 @@ static void osd_draw_bitmap(osd_object_t + osd->x2 = MAX( osd->x2, x1+width ); + osd->y1 = MIN( osd->y1, y1 ); + osd->y2 = MAX( osd->y2, y1+height ); ++ osd->area_touched = 1; + + for( y=0; yargb_layer.buffer != argb_buffer) { ++ dirty_x = 0; ++ dirty_y = 0; ++ dirty_width = osd->width; ++ dirty_height = osd->height; ++ } ++ ++ /* keep osd_object clipping behavior */ ++ osd->x1 = MIN( osd->x1, dirty_x ); ++ osd->x2 = MAX( osd->x2, dirty_x + dirty_width ); ++ osd->y1 = MIN( osd->y1, dirty_y ); ++ osd->y2 = MAX( osd->y2, dirty_y + dirty_height ); ++ ++ pthread_mutex_lock(&osd->argb_layer.mutex); ++ ++ /* argb layer update area accumulation */ ++ osd->argb_layer.x1 = MIN( osd->argb_layer.x1, dirty_x ); ++ osd->argb_layer.x2 = MAX( osd->argb_layer.x2, dirty_x + dirty_width ); ++ osd->argb_layer.y1 = MIN( osd->argb_layer.y1, dirty_y ); ++ osd->argb_layer.y2 = MAX( osd->argb_layer.y2, dirty_y + dirty_height ); ++ ++ osd->argb_layer.buffer = argb_buffer; ++ ++ pthread_mutex_unlock(&osd->argb_layer.mutex); ++} ++ + static uint32_t osd_get_capabilities (osd_object_t *osd) { + + osd_renderer_t *this = osd->renderer; + uint32_t capabilities = 0; ++ uint32_t vo_capabilities; + + #ifdef HAVE_FT2 + capabilities |= XINE_OSD_CAP_FREETYPE2; + #endif + + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); +- if( this->stream->video_out->get_capabilities(this->stream->video_out) & +- VO_CAP_UNSCALED_OVERLAY) +- capabilities |= XINE_OSD_CAP_UNSCALED; ++ vo_capabilities = this->stream->video_out->get_capabilities(this->stream->video_out); + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); + ++ if (vo_capabilities & VO_CAP_UNSCALED_OVERLAY) ++ capabilities |= XINE_OSD_CAP_UNSCALED; ++ ++ if (vo_capabilities & VO_CAP_CUSTOM_EXTENT_OVERLAY) ++ capabilities |= XINE_OSD_CAP_CUSTOM_EXTENT; ++ ++ if (vo_capabilities & VO_CAP_ARGB_LAYER_OVERLAY) ++ capabilities |= XINE_OSD_CAP_ARGB_LAYER; ++ ++ if (vo_capabilities & VO_CAP_VIDEO_WINDOW_OVERLAY) ++ capabilities |= XINE_OSD_CAP_VIDEO_WINDOW; ++ + return capabilities; + } + +@@ -1621,8 +1721,11 @@ osd_renderer_t *_x_osd_renderer_init( xi + this->get_text_size = osd_get_text_size; + this->close = osd_renderer_close; + this->draw_bitmap = osd_draw_bitmap; ++ this->set_argb_buffer = osd_set_argb_buffer; + this->show_unscaled = osd_show_unscaled; + this->get_capabilities = osd_get_capabilities; ++ this->set_extent = osd_set_extent; ++ this->set_video_window = osd_set_video_window; + + return this; + } +--- /dev/null ++++ xine-lib-1.1.19/src/xine-engine/accel_vdpau.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2008 the xine project ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * ++ * Common acceleration definitions for vdpau ++ * ++ * ++ */ ++ ++#ifndef HAVE_XINE_ACCEL_VDPAU_H ++#define HAVE_XINE_ACCEL_VDPAU_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++ ++ ++typedef struct { ++ vo_frame_t *vo_frame; ++ ++ VdpDevice vdp_device; ++ ++ VdpGetErrorString *vdp_get_error_string; ++ VdpDecoderCreate *vdp_decoder_create; ++ VdpDecoderDestroy *vdp_decoder_destroy; ++ VdpDecoderRender *vdp_decoder_render; ++ ++ VdpVideoSurface surface; ++ VdpChromaType chroma; ++ ++ VdpColorStandard color_standard; ++ ++ int vdp_runtime_nr; /* this is used to keep in sync on preemptions */ ++ int *current_vdp_runtime_nr; ++ ++} vdpau_accel_t; ++ ++#define VDPAU_DATA(frame_gen) ((frame_gen) ? (vdpau_accel_t *)(frame_gen)->accel_data : (vdpau_accel_t *)0) ++#define VDPAU_FRAME(frame_gen) ((frame_gen) ? (vdpau_accel_t *)VDPAU_DATA(frame_gen)->vo_frame : (vdpau_frame_t *)0) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif ++ +--- xine-lib-1.1.19.orig/src/xine-engine/video_out.c ++++ xine-lib-1.1.19/src/xine-engine/video_out.c +@@ -132,6 +132,9 @@ typedef struct { + int frame_drop_cpt; + int frame_drop_suggested; + int crop_left, crop_right, crop_top, crop_bottom; ++ pthread_mutex_t trigger_drawing_mutex; ++ pthread_cond_t trigger_drawing_cond; ++ int trigger_drawing; + } vos_t; + + +@@ -899,7 +902,7 @@ static vo_frame_t *get_next_frame (vos_t + int64_t *next_frame_vpts) { + + vo_frame_t *img; +- ++ + pthread_mutex_lock(&this->display_img_buf_queue->mutex); + + img = this->display_img_buf_queue->first; +@@ -930,8 +933,8 @@ static vo_frame_t *get_next_frame (vos_t + img->vpts = cur_vpts; + /* extra info of the backup is thrown away, because it is not up to date */ + _x_extra_info_reset(img->extra_info); ++ img->future_frame = NULL; + } +- + return img; + + } else { +@@ -990,6 +993,13 @@ static vo_frame_t *get_next_frame (vos_t + * remove frame from display queue and show it + */ + ++ if ( img ) { ++ if ( img->next ) ++ img->future_frame = img->next; ++ else ++ img->future_frame = NULL; ++ } ++ + img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); + pthread_mutex_unlock(&this->display_img_buf_queue->mutex); + +@@ -1068,6 +1078,32 @@ static void check_redraw_needed (vos_t * + this->redraw_needed = 1; + } + ++static int interruptable_sleep(vos_t *this, int usec_to_sleep) ++{ ++ int timedout = 0; ++ ++ struct timeval now; ++ gettimeofday(&now, 0); ++ ++ pthread_mutex_lock (&this->trigger_drawing_mutex); ++ if (!this->trigger_drawing) { ++ struct timespec abstime; ++ abstime.tv_sec = now.tv_sec + usec_to_sleep / 1000000; ++ abstime.tv_nsec = now.tv_usec * 1000 + (usec_to_sleep % 1000000) * 1000; ++ ++ if (abstime.tv_nsec > 1000000000) { ++ abstime.tv_nsec -= 1000000000; ++ abstime.tv_sec++; ++ } ++ ++ timedout = pthread_cond_timedwait(&this->trigger_drawing_cond, &this->trigger_drawing_mutex, &abstime); ++ } ++ this->trigger_drawing = 0; ++ pthread_mutex_unlock (&this->trigger_drawing_mutex); ++ ++ return timedout; ++} ++ + /* special loop for paused mode + * needed to update screen due overlay changes, resize, window + * movement, brightness adjusting etc. +@@ -1113,7 +1149,7 @@ static void paused_loop( vos_t *this, in + } + + pthread_mutex_unlock( &this->free_img_buf_queue->mutex ); +- xine_usec_sleep (20000); ++ interruptable_sleep(this, 20000); + pthread_mutex_lock( &this->free_img_buf_queue->mutex ); + } + +@@ -1243,7 +1279,10 @@ static void *video_out_loop (void *this_ + "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "\n", next_frame_vpts,vpts); + + if (usec_to_sleep > 0) +- xine_usec_sleep (usec_to_sleep); ++ { ++ if (0 == interruptable_sleep(this, usec_to_sleep)) ++ break; ++ } + + if (this->discard_frames) + break; +@@ -1427,6 +1466,8 @@ static int vo_get_property (xine_video_p + ret = this->crop_bottom; + break; + ++ case XINE_PARAM_VO_SHARPNESS: ++ case XINE_PARAM_VO_NOISE_REDUCTION: + case XINE_PARAM_VO_HUE: + case XINE_PARAM_VO_SATURATION: + case XINE_PARAM_VO_CONTRAST: +@@ -1521,6 +1562,8 @@ static int vo_set_property (xine_video_p + ret = this->crop_bottom = value; + break; + ++ case XINE_PARAM_VO_SHARPNESS: ++ case XINE_PARAM_VO_NOISE_REDUCTION: + case XINE_PARAM_VO_HUE: + case XINE_PARAM_VO_SATURATION: + case XINE_PARAM_VO_CONTRAST: +@@ -1632,6 +1675,9 @@ static void vo_exit (xine_video_port_t * + free (this->free_img_buf_queue); + free (this->display_img_buf_queue); + ++ pthread_cond_destroy(&this->trigger_drawing_cond); ++ pthread_mutex_destroy(&this->trigger_drawing_mutex); ++ + free (this); + } + +@@ -1701,6 +1747,15 @@ static void vo_flush (xine_video_port_t + } + } + ++static void vo_trigger_drawing (xine_video_port_t *this_gen) { ++ vos_t *this = (vos_t *) this_gen; ++ ++ pthread_mutex_lock (&this->trigger_drawing_mutex); ++ this->trigger_drawing = 1; ++ pthread_cond_signal (&this->trigger_drawing_cond); ++ pthread_mutex_unlock (&this->trigger_drawing_mutex); ++} ++ + /* crop_frame() will allocate a new frame to copy in the given image + * while cropping. maybe someday this will be an automatic post plugin. + */ +@@ -1796,6 +1851,7 @@ xine_video_port_t *_x_vo_new_port (xine_ + this->vo.enable_ovl = vo_enable_overlay; + this->vo.get_overlay_manager = vo_get_overlay_manager; + this->vo.flush = vo_flush; ++ this->vo.trigger_drawing = vo_trigger_drawing; + this->vo.get_property = vo_get_property; + this->vo.set_property = vo_set_property; + this->vo.status = vo_status; +@@ -1889,6 +1945,9 @@ xine_video_port_t *_x_vo_new_port (xine_ + "were not scheduled for display in time, xine sends a notification."), + 20, NULL, NULL); + ++ pthread_mutex_init(&this->trigger_drawing_mutex, NULL); ++ pthread_cond_init(&this->trigger_drawing_cond, NULL); ++ this->trigger_drawing = 0; + + if (grabonly) { + +--- xine-lib-1.1.19.orig/src/xine-engine/load_plugins.c ++++ xine-lib-1.1.19/src/xine-engine/load_plugins.c +@@ -1980,7 +1980,13 @@ video_decoder_t *_x_get_video_decoder (x + + vd = ((video_decoder_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream); + +- if (vd) { ++ if (vd == 1) { ++ /* HACK: plugin failed to instantiate because required resources are unavailable at that time, ++ but may be available later, so don't remove this plugin from catalog. */ ++ xprintf(stream->xine, XINE_VERBOSITY_DEBUG, ++ "load_plugins: plugin %s failed to instantiate, resources temporarily unavailable.\n", node->info->id); ++ } ++ else if (vd) { + inc_node_ref(node); + vd->node = node; + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, +--- xine-lib-1.1.19.orig/src/xine-engine/video_out.h ++++ xine-lib-1.1.19/src/xine-engine/video_out.h +@@ -64,6 +64,14 @@ struct vo_frame_s { + * member functions + */ + ++ /* Provide a copy of the frame's image in an image format already known to xine. data's member */ ++ /* have already been intialized to frame's content on entry, so it's usually only necessary to */ ++ /* change format and img_size. In case img is set, it will point to a memory block of suitable */ ++ /* size (size has been determined by a previous call with img == NULL). img content and img_size */ ++ /* must adhere to the specification of _x_get_current_frame_data(). */ ++ /* Currently this is needed for all image formats except XINE_IMGFMT_YV12 and XINE_IMGFMT_YUY2. */ ++ void (*proc_provide_standard_frame_data) (vo_frame_t *vo_img, xine_current_frame_data_t *data); ++ + /* Duplicate picture data and acceleration specific data of a frame. */ + /* if the image format isn't already known by Xine. Currently this is needed */ + /* For all image formats except XINE_IMGFMT_YV12 and XINE_IMGFMT_YUY2 */ +@@ -146,6 +154,9 @@ struct vo_frame_s { + /* displacement for overlays */ + int overlay_offset_x, overlay_offset_y; + ++ /* pointer to the next frame in display order, used by some vo deint */ ++ struct vo_frame_s *future_frame; ++ + /* + * that part is used only by video_out.c for frame management + * obs: changing anything here will require recompiling vo drivers +@@ -198,6 +209,9 @@ struct xine_video_port_s { + /* flush video_out fifo */ + void (*flush) (xine_video_port_t *self); + ++ /* trigger immediate drawing */ ++ void (*trigger_drawing) (xine_video_port_t *self); ++ + /* Get/Set video property + * + * See VO_PROP_* bellow +@@ -233,7 +247,7 @@ struct xine_video_port_s { + #define VO_PROP_AUTOPAINT_COLORKEY 7 + #define VO_PROP_ZOOM_X 8 + #define VO_PROP_PAN_SCAN 9 +-#define VO_PROP_TVMODE 10 ++#define VO_PROP_TVMODE 10 + #define VO_PROP_MAX_NUM_FRAMES 11 + #define VO_PROP_GAMMA 12 + #define VO_PROP_ZOOM_Y 13 +@@ -246,7 +260,9 @@ struct xine_video_port_s { + #define VO_PROP_OUTPUT_HEIGHT 20 /* read-only */ + #define VO_PROP_OUTPUT_XOFFSET 21 /* read-only */ + #define VO_PROP_OUTPUT_YOFFSET 22 /* read-only */ +-#define VO_NUM_PROPERTIES 23 ++#define VO_PROP_SHARPNESS 24 ++#define VO_PROP_NOISE_REDUCTION 25 ++#define VO_NUM_PROPERTIES 26 + + /* number of colors in the overlay palette. Currently limited to 256 + at most, because some alphablend functions use an 8-bit index into +@@ -268,6 +284,7 @@ struct xine_video_port_s { + #define VO_PAN_SCAN_FLAG 4 + #define VO_INTERLACED_FLAG 8 + #define VO_NEW_SEQUENCE_FLAG 16 /* set after MPEG2 Sequence Header Code (used by XvMC) */ ++#define VO_CHROMA_422 32 /* used by VDPAU, default is chroma_420 */ + + /* video driver capabilities */ + #define VO_CAP_YV12 0x00000001 /* driver can handle YUV 4:2:0 pictures */ +@@ -277,6 +294,12 @@ struct xine_video_port_s { + #define VO_CAP_UNSCALED_OVERLAY 0x00000010 /* driver can blend overlay at output resolution */ + #define VO_CAP_CROP 0x00000020 /* driver can crop */ + #define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ ++#define VO_CAP_VDPAU_H264 0x00000080 /* driver can use VDPAU for H264 */ ++#define VO_CAP_VDPAU_MPEG12 0x00000100 /* driver can use VDPAU for mpeg1/2 */ ++#define VO_CAP_VDPAU_VC1 0x00000200 /* driver can use VDPAU for mpeg1/2 */ ++#define VO_CAP_CUSTOM_EXTENT_OVERLAY 0x01000000 /* driver can blend custom extent overlay to output extent */ ++#define VO_CAP_ARGB_LAYER_OVERLAY 0x02000000 /* driver supports true color overlay */ ++#define VO_CAP_VIDEO_WINDOW_OVERLAY 0x04000000 /* driver can scale video to an area within overlay */ + + + /* +@@ -389,6 +412,14 @@ typedef struct rle_elem_s { + uint16_t color; + } rle_elem_t; + ++typedef struct argb_layer_s { ++ pthread_mutex_t mutex; ++ uint32_t *buffer; ++ /* dirty area */ ++ int x1, y1; ++ int x2, y2; ++} argb_layer_t; ++ + struct vo_overlay_s { + + rle_elem_t *rle; /* rle code buffer */ +@@ -399,6 +430,16 @@ struct vo_overlay_s { + int width; /* width of subpicture area */ + int height; /* height of subpicture area */ + ++ /* area within osd extent to scale video to */ ++ int video_window_x; ++ int video_window_y; ++ int video_window_width; ++ int video_window_height; ++ ++ /* extent of reference coordinate system */ ++ int extent_width; ++ int extent_height; ++ + uint32_t color[OVL_PALETTE_SIZE]; /* color lookup table */ + uint8_t trans[OVL_PALETTE_SIZE]; /* mixer key table */ + int rgb_clut; /* true if clut was converted to rgb */ +@@ -413,6 +454,9 @@ struct vo_overlay_s { + int hili_rgb_clut; /* true if clut was converted to rgb */ + + int unscaled; /* true if it should be blended unscaled */ ++ ++ ++ argb_layer_t *argb_layer; + }; + + +--- xine-lib-1.1.19.orig/src/xine-engine/xine_interface.c ++++ xine-lib-1.1.19/src/xine-engine/xine_interface.c +@@ -474,6 +474,8 @@ void xine_set_param (xine_stream_t *stre + stream->xine->verbosity = value; + break; + ++ case XINE_PARAM_VO_SHARPNESS: ++ case XINE_PARAM_VO_NOISE_REDUCTION: + case XINE_PARAM_VO_HUE: + case XINE_PARAM_VO_SATURATION: + case XINE_PARAM_VO_CONTRAST: +@@ -639,6 +641,8 @@ int xine_get_param (xine_stream_t *strea + ret = stream->xine->verbosity; + break; + ++ case XINE_PARAM_VO_SHARPNESS: ++ case XINE_PARAM_VO_NOISE_REDUCTION: + case XINE_PARAM_VO_HUE: + case XINE_PARAM_VO_SATURATION: + case XINE_PARAM_VO_CONTRAST: +@@ -860,6 +864,20 @@ void xine_osd_draw_bitmap(xine_osd_t *th + this->osd.renderer->draw_bitmap(&this->osd, bitmap, x1, y1, width, height, palette_map); + } + ++void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer, ++ int dirty_x, int dirty_y, int dirty_width, int dirty_height) { ++ this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer, dirty_x, dirty_y, dirty_width, dirty_height); ++} ++ ++void xine_osd_set_extent(xine_osd_t *this, int extent_width, int extent_height) { ++ this->osd.renderer->set_extent(&this->osd, extent_width, extent_height); ++} ++ ++void xine_osd_set_video_window(xine_osd_t *this, int window_x, int window_y, int window_width, int window_height) { ++ this->osd.renderer->set_video_window(&this->osd, window_x, window_y, window_width, window_height); ++} ++ ++ + const char *const *xine_post_list_inputs(xine_post_t *this_gen) { + post_plugin_t *this = (post_plugin_t *)this_gen; + return this->input_ids; +--- xine-lib-1.1.19.orig/src/xine-engine/xine.c ++++ xine-lib-1.1.19/src/xine-engine/xine.c +@@ -294,8 +294,37 @@ static void ticket_revoke(xine_ticket_t + pthread_mutex_unlock(&this->revoke_lock); + } + ++static int ticket_lock_port_rewiring(xine_ticket_t *this, int ms_timeout) { ++ ++ if (ms_timeout >= 0) { ++ struct timespec abstime; ++ ++ struct timeval now; ++ gettimeofday(&now, 0); ++ ++ abstime.tv_sec = now.tv_sec + ms_timeout / 1000; ++ abstime.tv_nsec = now.tv_usec * 1000 + (ms_timeout % 1000) * 1e6; ++ ++ if (abstime.tv_nsec > 1e9) { ++ abstime.tv_nsec -= 1e9; ++ abstime.tv_sec++; ++ } ++ ++ return (0 == pthread_mutex_timedlock(&this->port_rewiring_lock, &abstime)); ++ } ++ ++ pthread_mutex_lock(&this->port_rewiring_lock); ++ return 1; ++} ++ ++static void ticket_unlock_port_rewiring(xine_ticket_t *this) { ++ ++ pthread_mutex_unlock(&this->port_rewiring_lock); ++} ++ + static void ticket_dispose(xine_ticket_t *this) { + ++ pthread_mutex_destroy(&this->port_rewiring_lock); + pthread_mutex_destroy(&this->lock); + pthread_mutex_destroy(&this->revoke_lock); + pthread_cond_destroy(&this->issued); +@@ -317,12 +346,15 @@ static xine_ticket_t *XINE_MALLOC ticket + port_ticket->renew = ticket_renew; + port_ticket->issue = ticket_issue; + port_ticket->revoke = ticket_revoke; ++ port_ticket->lock_port_rewiring = ticket_lock_port_rewiring; ++ port_ticket->unlock_port_rewiring = ticket_unlock_port_rewiring; + port_ticket->dispose = ticket_dispose; + port_ticket->holder_thread_count = XINE_MAX_TICKET_HOLDER_THREADS; + port_ticket->holder_threads = calloc(XINE_MAX_TICKET_HOLDER_THREADS,sizeof(*port_ticket->holder_threads)); + + pthread_mutex_init(&port_ticket->lock, NULL); + pthread_mutex_init(&port_ticket->revoke_lock, NULL); ++ pthread_mutex_init(&port_ticket->port_rewiring_lock, NULL); + pthread_cond_init(&port_ticket->issued, NULL); + pthread_cond_init(&port_ticket->revoked, NULL); + +@@ -524,6 +556,7 @@ static int stream_rewire_audio(xine_post + if (!data) + return 0; + ++ stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1); + stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1); + + if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) { +@@ -534,6 +567,7 @@ static int stream_rewire_audio(xine_post + stream->audio_out = new_port; + + stream->xine->port_ticket->issue(stream->xine->port_ticket, 1); ++ stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket); + + return 1; + } +@@ -548,6 +582,7 @@ static int stream_rewire_video(xine_post + if (!data) + return 0; + ++ stream->xine->port_ticket->lock_port_rewiring(stream->xine->port_ticket, -1); + stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1); + + if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) { +@@ -558,6 +593,7 @@ static int stream_rewire_video(xine_post + stream->video_out = new_port; + + stream->xine->port_ticket->issue(stream->xine->port_ticket, 1); ++ stream->xine->port_ticket->unlock_port_rewiring(stream->xine->port_ticket); + + return 1; + } +@@ -1973,6 +2009,8 @@ static int _x_get_current_frame_data (xi + + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); + frame = stream->video_out->get_last_frame (stream->video_out); ++ if (frame) ++ frame->lock(frame); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + + if (!frame) { +@@ -2004,6 +2042,30 @@ static int _x_get_current_frame_data (xi + + switch (frame->format) { + ++ default: ++ if (frame->proc_provide_standard_frame_data) { ++ uint8_t *img = data->img; ++ size_t img_size = data->img_size; ++ data->img = 0; ++ data->img_size = 0; ++ ++ /* ask frame implementation for required img buffer size */ ++ frame->proc_provide_standard_frame_data(frame, data); ++ required_size = data->img_size; ++ ++ data->img = img; ++ data->img_size = img_size; ++ break; ++ } ++ ++ if (!data->img && !(flags & XINE_FRAME_DATA_ALLOCATE_IMG)) ++ break; /* not interested in image data */ ++ ++ xprintf (stream->xine, XINE_VERBOSITY_DEBUG, ++ "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); ++ /* fall though and provide "green" YV12 image */ ++ data->format = XINE_IMGFMT_YV12; ++ + case XINE_IMGFMT_YV12: + required_size = frame->width * frame->height + + ((frame->width + 1) / 2) * ((frame->height + 1) / 2) +@@ -2016,26 +2078,21 @@ static int _x_get_current_frame_data (xi + + ((frame->width + 1) / 2) * frame->height; + break; + +- default: +- if (data->img || (flags & XINE_FRAME_DATA_ALLOCATE_IMG)) { +- xprintf (stream->xine, XINE_VERBOSITY_DEBUG, +- "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); +- _x_abort (); +- } +- +- required_size = 0; + } + + if (flags & XINE_FRAME_DATA_ALLOCATE_IMG) { + /* return allocated buffer size */ + data->img_size = required_size; + /* allocate img or fail */ +- if (!(data->img = calloc(1, required_size))) ++ if (!(data->img = calloc(1, required_size))) { ++ frame->free(frame); + return 0; ++ } + } else { + /* fail if supplied buffer is to small */ + if (data->img && !img_size_unknown && data->img_size < required_size) { + data->img_size = required_size; ++ frame->free(frame); + return 0; + } + /* return used buffer size */ +@@ -2071,11 +2128,14 @@ static int _x_get_current_frame_data (xi + break; + + default: +- xprintf (stream->xine, XINE_VERBOSITY_DEBUG, +- "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); +- _x_abort (); ++ if (frame->proc_provide_standard_frame_data) ++ frame->proc_provide_standard_frame_data(frame, data); ++ else if (!(flags & XINE_FRAME_DATA_ALLOCATE_IMG)) ++ memset(data->img, 0, data->img_size); + } + } ++ ++ frame->free(frame); + return 1; + } + +@@ -2340,3 +2400,83 @@ int _x_query_buffer_usage(xine_stream_t + + return ticket_acquired != 0; + } ++ ++int _x_lock_port_rewiring(xine_t *xine, int ms_timeout) ++{ ++ return xine->port_ticket->lock_port_rewiring(xine->port_ticket, ms_timeout); ++} ++ ++void _x_unlock_port_rewiring(xine_t *xine) ++{ ++ xine->port_ticket->unlock_port_rewiring(xine->port_ticket); ++} ++ ++int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out) ++{ ++ if (ms_to_time_out >= 0) { ++ struct timespec abstime; ++ ++ struct timeval now; ++ gettimeofday(&now, 0); ++ ++ abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000; ++ abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6; ++ ++ if (abstime.tv_nsec > 1e9) { ++ abstime.tv_nsec -= 1e9; ++ abstime.tv_sec++; ++ } ++ ++ return (0 == pthread_mutex_timedlock(&stream->frontend_lock, &abstime)); ++ } ++ ++ pthread_mutex_lock(&stream->frontend_lock); ++ return 1; ++} ++ ++void _x_unlock_frontend(xine_stream_t *stream) ++{ ++ pthread_mutex_unlock(&stream->frontend_lock); ++} ++ ++int _x_query_unprocessed_osd_events(xine_stream_t *stream) ++{ ++ video_overlay_manager_t *ovl; ++ int redraw_needed; ++ ++ if (!stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1)) ++ return -1; ++ ++ ovl = stream->video_out->get_overlay_manager(stream->video_out); ++ redraw_needed = ovl->redraw_needed(ovl, 0); ++ ++ if (redraw_needed) ++ stream->video_out->trigger_drawing(stream->video_out); ++ ++ stream->xine->port_ticket->release_nonblocking(stream->xine->port_ticket, 1); ++ ++ return redraw_needed; ++} ++ ++int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing) ++{ ++ if (!stream->demux_plugin) ++ return -1; ++ return stream->demux_plugin->seek(stream->demux_plugin, start_pos, start_time, playing); ++} ++ ++int _x_continue_stream_processing(xine_stream_t *stream) ++{ ++ return stream->status != XINE_STATUS_STOP ++ && stream->status != XINE_STATUS_QUIT; ++} ++ ++void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream) ++{ ++ stream->first_frame_flag = 2; ++} ++ ++void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream) ++{ ++ stream->first_frame_flag = 1; ++} +--- xine-lib-1.1.19.orig/src/xine-engine/video_overlay.h ++++ xine-lib-1.1.19/src/xine-engine/video_overlay.h +@@ -35,7 +35,7 @@ + + #define MAX_OBJECTS 50 + #define MAX_EVENTS 50 +-#define MAX_SHOWING 16 ++#define MAX_SHOWING (5 + 16) + + #define OVERLAY_EVENT_NULL 0 + #define OVERLAY_EVENT_SHOW 1 +--- xine-lib-1.1.19.orig/src/xine-engine/accel_xvmc.h ++++ xine-lib-1.1.19/src/xine-engine/accel_xvmc.h +@@ -65,6 +65,7 @@ typedef struct xine_vld_frame_s { + + + typedef struct xine_xvmc_s { ++ vo_frame_t *vo_frame; + xine_macroblocks_t *macroblocks; + void (*proc_macro_block)(int x,int y,int mb_type, + int motion_type,int (*mv_field_sel)[2], +@@ -74,6 +75,9 @@ typedef struct xine_xvmc_s { + int second_field,int (*f_mot_pmv)[2],int (*b_mot_pmv)[2]); + } xine_xvmc_t ; + ++#define XVMC_DATA(frame_gen) ((frame_gen) ? (xine_xvmc_t *)(frame_gen)->accel_data : (xine_xvmc_t *)0) ++#define XVMC_FRAME(frame_gen) ((frame_gen) ? (xvmc_frame_t *)XVMC_DATA(frame_gen)->vo_frame : (xvmc_frame_t *)0) ++ + typedef struct xine_xxmc_s { + + /* +@@ -108,6 +112,9 @@ typedef struct xine_xxmc_s { + void (*proc_xxmc_unlock) (vo_driver_t *this_gen); + } xine_xxmc_t; + ++#define XXMC_DATA(frame_gen) ((frame_gen) ? (xine_xxmc_t *)(frame_gen)->accel_data : (xine_xxmc_t *)0) ++#define XXMC_FRAME(frame_gen) ((frame_gen) ? (xxmc_frame_t *)XXMC_DATA(frame_gen)->xvmc.vo_frame : (xxmc_frame_t *)0) ++ + /* + * Register XvMC stream types here. + */ +--- xine-lib-1.1.19.orig/src/xine-engine/xine_internal.h ++++ xine-lib-1.1.19/src/xine-engine/xine_internal.h +@@ -169,6 +169,9 @@ struct xine_ticket_s { + * be used in combination with acquire_nonblocking() */ + void (*release_nonblocking)(xine_ticket_t *self, int irrevocable); + ++ int (*lock_port_rewiring)(xine_ticket_t *self, int ms_timeout); ++ void (*unlock_port_rewiring)(xine_ticket_t *self); ++ + void (*dispose)(xine_ticket_t *self); + + pthread_mutex_t lock; +@@ -185,6 +188,7 @@ struct xine_ticket_s { + pthread_t holder; + } *holder_threads; + unsigned holder_thread_count; ++ pthread_mutex_t port_rewiring_lock; + #endif + }; + +@@ -375,6 +379,15 @@ struct xine_stream_s { + */ + + int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *num_audio_buffers, int *num_video_frames, int *num_audio_frames) XINE_PROTECTED; ++int _x_lock_port_rewiring(xine_t *xine, int ms_to_time_out) XINE_PROTECTED; ++void _x_unlock_port_rewiring(xine_t *xine) XINE_PROTECTED; ++int _x_lock_frontend(xine_stream_t *stream, int ms_to_time_out) XINE_PROTECTED; ++void _x_unlock_frontend(xine_stream_t *stream) XINE_PROTECTED; ++int _x_query_unprocessed_osd_events(xine_stream_t *stream) XINE_PROTECTED; ++int _x_demux_seek(xine_stream_t *stream, off_t start_pos, int start_time, int playing) XINE_PROTECTED; ++int _x_continue_stream_processing(xine_stream_t *stream) XINE_PROTECTED; ++void _x_trigger_relaxed_frame_drop_mode(xine_stream_t *stream) XINE_PROTECTED; ++void _x_reset_relaxed_frame_drop_mode(xine_stream_t *stream) XINE_PROTECTED; + + void _x_handle_stream_end (xine_stream_t *stream, int non_user) XINE_PROTECTED; + +--- xine-lib-1.1.19.orig/src/xine-engine/post.c ++++ xine-lib-1.1.19/src/xine-engine/post.c +@@ -144,6 +144,14 @@ static void post_video_flush(xine_video_ + if (port->port_lock) pthread_mutex_unlock(port->port_lock); + } + ++static void post_video_trigger_drawing(xine_video_port_t *port_gen) { ++ post_video_port_t *port = (post_video_port_t *)port_gen; ++ ++ if (port->port_lock) pthread_mutex_lock(port->port_lock); ++ port->original_port->trigger_drawing(port->original_port); ++ if (port->port_lock) pthread_mutex_unlock(port->port_lock); ++} ++ + static int post_video_status(xine_video_port_t *port_gen, xine_stream_t *stream, + int *width, int *height, int64_t *img_duration) { + post_video_port_t *port = (post_video_port_t *)port_gen; +@@ -187,6 +195,7 @@ static int post_video_rewire(xine_post_o + if (!new_port) + return 0; + ++ this->running_ticket->lock_port_rewiring(this->running_ticket, -1); + this->running_ticket->revoke(this->running_ticket, 1); + + if (input_port->original_port->status(input_port->original_port, input_port->stream, +@@ -197,6 +206,7 @@ static int post_video_rewire(xine_post_o + input_port->original_port = new_port; + + this->running_ticket->issue(this->running_ticket, 1); ++ this->running_ticket->unlock_port_rewiring(this->running_ticket); + + return 1; + } +@@ -218,6 +228,7 @@ post_video_port_t *_x_post_intercept_vid + port->new_port.exit = post_video_exit; + port->new_port.get_overlay_manager = post_video_get_overlay_manager; + port->new_port.flush = post_video_flush; ++ port->new_port.trigger_drawing = post_video_trigger_drawing; + port->new_port.status = post_video_status; + port->new_port.get_property = post_video_get_property; + port->new_port.set_property = post_video_set_property; +@@ -378,9 +389,10 @@ vo_frame_t *_x_post_intercept_video_fram + new_frame->dispose = + port->new_frame->dispose ? port->new_frame->dispose : post_frame_dispose; + +- if (!port->new_frame->draw) { ++ if (!port->new_frame->draw || (port->route_preprocessing_procs && port->route_preprocessing_procs(port, frame))) { + /* draw will most likely modify the frame, so the decoder +- * should only request preprocessing when there is no new draw */ ++ * should only request preprocessing when there is no new draw ++ * but route_preprocessing_procs() can override this decision */ + if (frame->proc_frame && !new_frame->proc_frame) + new_frame->proc_frame = post_frame_proc_frame; + if (frame->proc_slice && !new_frame->proc_slice) +@@ -697,6 +709,7 @@ static int post_audio_rewire(xine_post_o + if (!new_port) + return 0; + ++ this->running_ticket->lock_port_rewiring(this->running_ticket, -1); + this->running_ticket->revoke(this->running_ticket, 1); + + if (input_port->original_port->status(input_port->original_port, input_port->stream, +@@ -707,6 +720,7 @@ static int post_audio_rewire(xine_post_o + input_port->original_port = new_port; + + this->running_ticket->issue(this->running_ticket, 1); ++ this->running_ticket->unlock_port_rewiring(this->running_ticket); + + return 1; + } +--- xine-lib-1.1.19.orig/src/xine-engine/osd.h ++++ xine-lib-1.1.19/src/xine-engine/osd.h +@@ -47,8 +47,16 @@ struct osd_object_s { + + int width, height; /* work area dimentions */ + uint8_t *area; /* work area */ ++ int area_touched; /* work area was used for painting */ + int display_x,display_y; /* where to display it in screen */ + ++ /* video output area within osd extent */ ++ int video_window_x, video_window_y; ++ int video_window_width, video_window_height; ++ ++ /* extent of reference coordinate system */ ++ int extent_width, extent_height; ++ + /* clipping box inside work area */ + int x1, y1; + int x2, y2; +@@ -65,6 +73,13 @@ struct osd_object_s { + + osd_font_t *font; + osd_ft2context_t *ft2; ++ ++ ++ /* this holds an optional ARGB overlay, which ++ * is only be used by supported video_out modules. ++ * right now this is only vdpau */ ++ argb_layer_t argb_layer; ++ + }; + + /* this one is public */ +@@ -211,6 +226,35 @@ struct osd_renderer_s { + */ + uint32_t (*get_capabilities) (osd_object_t *osd); + ++ /* ++ * define extent of reference coordinate system for video ++ * resolution independent osds. both sizes must be > 0 to ++ * take effect. otherwise, video resolution will be used. ++ */ ++ void (*set_extent) (osd_object_t *osd, int extent_width, int extent_height); ++ ++ /* ++ * set an argb buffer to be blended into video ++ * the buffer must exactly match the osd dimensions ++ * and stay valid while the osd is on screen. pass ++ * a NULL pointer to safely remove the buffer from ++ * the osd layer. only the dirty area will be ++ * updated on screen. for convinience the whole ++ * osd object will be considered dirty when setting ++ * a different buffer pointer. ++ * see also XINE_OSD_CAP_ARGB_LAYER ++ */ ++ void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer, ++ int dirty_x, int dirty_y, int dirty_width, int dirty_height); ++ ++ /* ++ * osd video window defines an area withing osd extent where the ++ * video shall be scaled to while an osd is displayed on screen. ++ * both width and height must be > 0 to take effect. ++ */ ++ void (*set_video_window) (osd_object_t *osd, ++ int window_x, int window_y, int window_width, int window_height); ++ + /* private stuff */ + + pthread_mutex_t osd_mutex; +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/dpb.c +@@ -0,0 +1,409 @@ ++/* ++ * Copyright (C) 2008 Julian Scheel ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * dpb.c: Implementing Decoded Picture Buffer ++ */ ++ ++#include ++#include ++#include ++ ++#include "dpb.h" ++#include "nal.h" ++#include "video_out.h" ++ ++struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, ++ VdpVideoSurface surface, vo_frame_t *img) ++{ ++ struct decoded_picture *pic = calloc(1, sizeof(struct decoded_picture)); ++ pic->nal = init_nal_unit(); ++ copy_nal_unit(pic->nal, src_nal); ++ pic->top_is_reference = pic->nal->slc->field_pic_flag ++ ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; ++ pic->bottom_is_reference = pic->nal->slc->field_pic_flag ++ ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1; ++ pic->surface = surface; ++ pic->img = img; ++ ++ return pic; ++} ++ ++void free_decoded_picture(struct decoded_picture *pic) ++{ ++ pic->img->free(pic->img); ++ free_nal_unit(pic->nal); ++ free(pic); ++} ++ ++struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ struct decoded_picture *outpic = NULL; ++ ++ if(!do_flush && dpb->used < MAX_DPB_SIZE) ++ return NULL; ++ ++ if (pic != NULL) ++ do { ++ if (pic->delayed_output && ++ (outpic == NULL || ++ (pic->nal->top_field_order_cnt <= outpic->nal->top_field_order_cnt && ++ pic->nal->bottom_field_order_cnt <= outpic->nal->bottom_field_order_cnt)|| ++ (outpic->nal->top_field_order_cnt < 0 && pic->nal->top_field_order_cnt > 0 && ++ outpic->nal->bottom_field_order_cnt < 0 && pic->nal->bottom_field_order_cnt > 0)|| ++ outpic->nal->nal_unit_type == NAL_SLICE_IDR)) ++ outpic = pic; ++ } while ((pic = pic->next) != NULL); ++ ++ return outpic; ++} ++ ++struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ ++ if (pic != NULL) ++ do { ++ if (pic->nal->curr_pic_num == picnum) ++ return pic; ++ } while ((pic = pic->next) != NULL); ++ ++ return NULL; ++} ++ ++struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, ++ uint32_t longterm_picnum) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ ++ if (pic != NULL) ++ do { ++ if (pic->nal->long_term_pic_num == longterm_picnum) ++ return pic; ++ } while ((pic = pic->next) != NULL); ++ ++ return NULL; ++} ++ ++struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, ++ uint32_t longterm_idx) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ ++ if (pic != NULL) ++ do { ++ if (pic->nal->long_term_frame_idx == longterm_idx) ++ return pic; ++ } while ((pic = pic->next) != NULL); ++ ++ return NULL; ++} ++ ++int dpb_set_unused_ref_picture_a(struct dpb *dpb, struct decoded_picture *refpic) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ if (pic != NULL) ++ do { ++ if (pic == refpic) { ++ pic->used_for_reference = 0; ++ if(!pic->delayed_output) ++ dpb_remove_picture(dpb, pic); ++ return 0; ++ } ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ if (pic != NULL) ++ do { ++ if (pic->nal->curr_pic_num == picnum) { ++ pic->used_for_reference = 0; ++ if(!pic->delayed_output) ++ dpb_remove_picture(dpb, pic); ++ return 0; ++ } ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ if (pic != NULL) ++ do { ++ if (pic->nal->long_term_pic_num == longterm_picnum) { ++ pic->used_for_reference = 0; ++ if(!pic->delayed_output) ++ dpb_remove_picture(dpb, pic); ++ return 0; ++ } ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ if (pic != NULL) ++ do { ++ if (pic->nal->long_term_frame_idx == longterm_idx) { ++ pic->nal->used_for_long_term_ref = 0; ++ pic->used_for_reference = 0; ++ if(!pic->delayed_output) ++ dpb_remove_picture(dpb, pic); ++ return 0; ++ } ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ if (pic != NULL) ++ do { ++ if (pic->nal->long_term_frame_idx >= longterm_idx) { ++ pic->used_for_reference = 0; ++ if(!pic->delayed_output) { ++ struct decoded_picture *next_pic = pic->next; ++ dpb_remove_picture(dpb, pic); ++ pic = next_pic; ++ continue; ++ } ++ } ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++ ++int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ if (pic != NULL) ++ do { ++ if (pic == outpic) { ++ pic->delayed_output = 0; ++ if(!pic->used_for_reference) ++ dpb_remove_picture(dpb, pic); ++ return 0; ++ } ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ struct decoded_picture *last_pic = NULL; ++ ++ if (pic != NULL) ++ do { ++ if (pic == rempic) { ++ // FIXME: free the picture.... ++ ++ if (last_pic != NULL) ++ last_pic->next = pic->next; ++ else ++ dpb->pictures = pic->next; ++ free_decoded_picture(pic); ++ dpb->used--; ++ return 0; ++ } ++ ++ last_pic = pic; ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++static int dpb_remove_picture_by_img(struct dpb *dpb, vo_frame_t *remimg) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ struct decoded_picture *last_pic = NULL; ++ ++ if (pic != NULL) ++ do { ++ if (pic->img == remimg) { ++ // FIXME: free the picture.... ++ ++ if (last_pic != NULL) ++ last_pic->next = pic->next; ++ else ++ dpb->pictures = pic->next; ++ free_decoded_picture(pic); ++ dpb->used--; ++ return 0; ++ } ++ ++ last_pic = pic; ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ struct decoded_picture *last_pic = NULL; ++ ++ if (pic != NULL) ++ do { ++ if (pic->nal->curr_pic_num == picnum) { ++ dpb_remove_picture(dpb, pic); ++ } ++ ++ last_pic = pic; ++ } while ((pic = pic->next) != NULL); ++ ++ return -1; ++} ++ ++int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames) ++{ ++ pic->img->lock(pic->img); ++ if (0 == dpb_remove_picture_by_img(dpb, pic->img)) ++ fprintf(stderr, "broken stream: current img was already in dpb -- freed it\n"); ++ else ++ pic->img->free(pic->img); ++ ++ int i = 0; ++ struct decoded_picture *last_pic = dpb->pictures; ++ ++ pic->next = dpb->pictures; ++ dpb->pictures = pic; ++ dpb->num_ref_frames = num_ref_frames; ++ dpb->used++; ++ ++ if(pic != NULL && dpb->used > num_ref_frames) { ++ do { ++ if(pic->used_for_reference) { ++ i++; ++ if(i>num_ref_frames) { ++ pic->used_for_reference = 0; ++ if(pic == dpb->pictures) ++ last_pic = pic->next; ++ ++ if(!pic->delayed_output) { ++ dpb_remove_picture(dpb, pic); ++ } ++ pic = last_pic; ++ if(pic == dpb->pictures) ++ continue; ++ } ++ last_pic = pic; ++ } ++ } while (pic != NULL && (pic = pic->next) != NULL); ++ } ++ ++ return 0; ++} ++ ++int dpb_flush(struct dpb *dpb) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ ++ if (pic != NULL) ++ do { ++ struct decoded_picture *next_pic = pic->next; ++ dpb_set_unused_ref_picture_a(dpb, pic); ++ pic = next_pic; ++ } while (pic != NULL); ++ ++ //printf("Flushed, used: %d\n", dpb->used); ++ ++ return 0; ++} ++ ++void dpb_free_all( struct dpb *dpb ) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ ++ if (pic != NULL) ++ do { ++ struct decoded_picture *next_pic = pic->next; ++ free_decoded_picture(pic); ++ --dpb->used; ++ pic = next_pic; ++ } while (pic != NULL); ++ ++ printf("dpb_free_all, used: %d\n", dpb->used); ++ dpb->pictures = NULL; ++} ++ ++void dpb_clear_all_pts( struct dpb *dpb ) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ ++ while (pic != NULL) { ++ pic->img->pts = 0; ++ pic = pic->next; ++ } ++} ++ ++int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) ++{ ++ struct decoded_picture *pic = dpb->pictures; ++ struct decoded_picture *last_pic = NULL; ++ ++ int i = 0; ++ int used_refframes = 0; ++ ++ if (pic != NULL) ++ do { ++ if (pic->used_for_reference) { ++ reflist[i].surface = pic->surface; ++ reflist[i].is_long_term = pic->nal->used_for_long_term_ref; ++ if(reflist[i].is_long_term) ++ reflist[i].frame_idx = pic->nal->slc->frame_num; ++ else ++ reflist[i].frame_idx = pic->nal->slc->frame_num; ++ reflist[i].top_is_reference = pic->top_is_reference; ++ reflist[i].bottom_is_reference = pic->bottom_is_reference; ++ reflist[i].field_order_cnt[0] = pic->nal->top_field_order_cnt; ++ reflist[i].field_order_cnt[1] = pic->nal->bottom_field_order_cnt; ++ i++; ++ } ++ last_pic = pic; ++ } while ((pic = pic->next) != NULL && i < 16); ++ ++ used_refframes = i; ++ ++ // fill all other frames with invalid handles ++ while(i < 16) { ++ reflist[i].bottom_is_reference = VDP_FALSE; ++ reflist[i].top_is_reference = VDP_FALSE; ++ reflist[i].frame_idx = 0; ++ reflist[i].is_long_term = VDP_FALSE; ++ reflist[i].surface = VDP_INVALID_HANDLE; ++ reflist[i].field_order_cnt[0] = 0; ++ reflist[i].field_order_cnt[1] = 0; ++ i++; ++ } ++ ++ return used_refframes; ++} +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/vdpau_h264.c +@@ -0,0 +1,892 @@ ++/* ++ * Copyright (C) 2008 Julian Scheel ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * vdpau_h264.c: H264 Video Decoder utilizing nvidia VDPAU engine ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xine_internal.h" ++#include "video_out.h" ++#include "buffer.h" ++#include "xineutils.h" ++#include "bswap.h" ++#include "accel_vdpau.h" ++#include "h264_parser.h" ++#include "dpb.h" ++ ++#define VIDEOBUFSIZE 128*1024 ++ ++typedef struct { ++ video_decoder_class_t decoder_class; ++} vdpau_h264_class_t; ++ ++typedef struct vdpau_h264_decoder_s { ++ video_decoder_t video_decoder; /* parent video decoder structure */ ++ ++ vdpau_h264_class_t *class; ++ xine_stream_t *stream; ++ ++ /* these are traditional variables in a video decoder object */ ++ uint64_t video_step; /* frame duration in pts units */ ++ ++ int width; /* the width of a video frame */ ++ int height; /* the height of a video frame */ ++ double ratio; /* the width to height ratio */ ++ ++ ++ struct nal_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ ++ uint8_t wait_for_bottom_field; ++ struct decoded_picture *last_ref_pic; ++ uint32_t last_top_field_order_cnt; ++ ++ int have_frame_boundary_marks; ++ int wait_for_frame_start; ++ ++ VdpDecoder decoder; ++ int decoder_started; ++ ++ VdpColorStandard color_standard; ++ VdpDecoderProfile profile; ++ vdpau_accel_t *vdpau_accel; ++ ++ xine_t *xine; ++ ++ int64_t curr_pts; ++ int64_t next_pts; ++ ++ vo_frame_t *last_img; ++ vo_frame_t *dangling_img; ++ ++ uint8_t *codec_private; ++ uint32_t codec_private_len; ++ ++ int vdp_runtime_nr; ++ ++} vdpau_h264_decoder_t; ++ ++static void vdpau_h264_reset (video_decoder_t *this_gen); ++static void vdpau_h264_flush (video_decoder_t *this_gen); ++ ++/************************************************************************** ++ * vdpau_h264 specific decode functions ++ *************************************************************************/ ++ ++/************************************************************************** ++ * xine video plugin functions ++ *************************************************************************/ ++ ++ ++static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) ++{ ++ printf("C: slice_count: %d\n", pic->slice_count); ++ printf("C: field_order_cnt[0]: %d\n", pic->field_order_cnt[0]); ++ printf("C: field_order_cnt[1]: %d\n", pic->field_order_cnt[1]); ++ printf("C: is_reference: %d\n", pic->is_reference); ++ printf("C: frame_num: %d\n", pic->frame_num); ++ printf("C: field_pic_flag: %d\n", pic->field_pic_flag); ++ printf("C: bottom_field_flag: %d\n", pic->bottom_field_flag); ++ printf("C: num_ref_frames: %d\n", pic->num_ref_frames); ++ printf("C: mb_adaptive_frame_field_flag: %d\n", pic->mb_adaptive_frame_field_flag); ++ printf("C: constrained_intra_pred_flag: %d\n", pic->constrained_intra_pred_flag); ++ printf("C: weighted_pred_flag: %d\n", pic->weighted_pred_flag); ++ printf("C: weighted_bipred_idc: %d\n", pic->weighted_bipred_idc); ++ printf("C: frame_mbs_only_flag: %d\n", pic->frame_mbs_only_flag); ++ printf("C: transform_8x8_mode_flag: %d\n", pic->transform_8x8_mode_flag); ++ printf("C: chroma_qp_index_offset: %d\n", pic->chroma_qp_index_offset); ++ printf("C: second_chroma_qp_index_offset: %d\n", pic->second_chroma_qp_index_offset); ++ printf("C: pic_init_qp_minus26: %d\n", pic->pic_init_qp_minus26); ++ printf("C: num_ref_idx_l0_active_minus1: %d\n", pic->num_ref_idx_l0_active_minus1); ++ printf("C: num_ref_idx_l1_active_minus1: %d\n", pic->num_ref_idx_l1_active_minus1); ++ printf("C: log2_max_frame_num_minus4: %d\n", pic->log2_max_frame_num_minus4); ++ printf("C: pic_order_cnt_type: %d\n", pic->pic_order_cnt_type); ++ printf("C: log2_max_pic_order_cnt_lsb_minus4: %d\n", pic->log2_max_pic_order_cnt_lsb_minus4); ++ printf("C: delta_pic_order_always_zero_flag: %d\n", pic->delta_pic_order_always_zero_flag); ++ printf("C: direct_8x8_inference_flag: %d\n", pic->direct_8x8_inference_flag); ++ printf("C: entropy_coding_mode_flag: %d\n", pic->entropy_coding_mode_flag); ++ printf("C: pic_order_present_flag: %d\n", pic->pic_order_present_flag); ++ printf("C: deblocking_filter_control_present_flag: %d\n", pic->deblocking_filter_control_present_flag); ++ printf("C: redundant_pic_cnt_present_flag: %d\n", pic->redundant_pic_cnt_present_flag); ++ ++ int i, j; ++ for(i = 0; i < 6; i++) { ++ printf("C: scalint_list4x4[%d]:\nC:", i); ++ for(j = 0; j < 16; j++) { ++ printf(" [%d]", pic->scaling_lists_4x4[i][j]); ++ if(j%8 == 0) ++ printf("\nC:"); ++ } ++ printf("C: \n"); ++ } ++ for(i = 0; i < 2; i++) { ++ printf("C: scalint_list8x8[%d]:\nC:", i); ++ for(j = 0; j < 64; j++) { ++ printf(" [%d] ", pic->scaling_lists_8x8[i][j]); ++ if(j%8 == 0) ++ printf("\nC:"); ++ } ++ printf("C: \n"); ++ } ++ ++ //int i; ++ for(i = 0; i < 16; i++) { ++ if(pic->referenceFrames[i].surface != VDP_INVALID_HANDLE) { ++ printf("C: -------------------\n"); ++ printf("C: Reference Frame %d:\n", i); ++ printf("C: frame_idx: %d\n", pic->referenceFrames[i].frame_idx); ++ printf("C: field_order_cnt[0]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); ++ printf("C: field_order_cnt[1]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); ++ printf("C: is_long_term: %d\n", pic->referenceFrames[i].is_long_term); ++ printf("C: top_is_reference: %d\n", pic->referenceFrames[i].top_is_reference); ++ printf("C: bottom_is_reference: %d\n", pic->referenceFrames[i].bottom_is_reference); ++ } ++ } ++ printf("C: ---------------------------------------------------------------\n"); ++ /*memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); ++ memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); ++ memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames));*/ ++ ++} ++ ++static void set_ratio(video_decoder_t *this_gen) ++{ ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; ++ ++ this->ratio = (double)this->width / (double)this->height; ++ if(this->nal_parser->current_nal->sps->vui_parameters.aspect_ration_info_present_flag) { ++ switch(this->nal_parser->current_nal->sps->vui_parameters.aspect_ratio_idc) { ++ case ASPECT_1_1: ++ this->ratio = 1 * this->ratio; ++ break; ++ case ASPECT_12_11: ++ this->ratio *= 12.0/11.0; ++ break; ++ case ASPECT_10_11: ++ this->ratio *= 10.0/11.0; ++ break; ++ case ASPECT_16_11: ++ this->ratio *= 16.0/11.0; ++ break; ++ case ASPECT_40_33: ++ this->ratio *= 40.0/33.0; ++ break; ++ case ASPECT_24_11: ++ this->ratio *= 24.0/11.0; ++ break; ++ case ASPECT_20_11: ++ this->ratio *= 20.0/11.0; ++ break; ++ case ASPECT_32_11: ++ this->ratio *= 32.0/11.0; ++ break; ++ case ASPECT_80_33: ++ this->ratio *= 80.0/33.0; ++ break; ++ case ASPECT_18_11: ++ this->ratio *= 18.0/11.0; ++ break; ++ case ASPECT_15_11: ++ this->ratio *= 15.0/11.0; ++ break; ++ case ASPECT_64_33: ++ this->ratio *= 64.0/33.0; ++ break; ++ case ASPECT_160_99: ++ this->ratio *= 160.0/99.0; ++ break; ++ case ASPECT_4_3: ++ this->ratio *= 4.0/3.0; ++ break; ++ case ASPECT_3_2: ++ this->ratio *= 3.0/2.0; ++ break; ++ case ASPECT_2_1: ++ this->ratio *= 2.0/1.0; ++ break; ++ case ASPECT_EXTENDED_SAR: ++ this->ratio *= ++ (double)this->nal_parser->current_nal->sps->vui_parameters.sar_width/ ++ (double)this->nal_parser->current_nal->sps->vui_parameters.sar_height; ++ break; ++ } ++ } ++} ++ ++static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slice_count, VdpPictureInfoH264 *pic) ++{ ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; ++ ++ struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; ++ struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; ++ struct slice_header *slc = this->nal_parser->current_nal->slc; ++ ++ pic->slice_count = slice_count; ++ pic->field_order_cnt[0] = this->nal_parser->current_nal->top_field_order_cnt; ++ pic->field_order_cnt[1] = this->nal_parser->current_nal->bottom_field_order_cnt; ++ pic->is_reference = ++ (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; ++ pic->frame_num = slc->frame_num; ++ pic->field_pic_flag = slc->field_pic_flag; ++ pic->bottom_field_flag = slc->bottom_field_flag; ++ pic->num_ref_frames = sps->num_ref_frames; ++ pic->mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag && !slc->field_pic_flag; ++ pic->constrained_intra_pred_flag = pps->constrained_intra_pred_flag; ++ pic->weighted_pred_flag = pps->weighted_pred_flag; ++ pic->weighted_bipred_idc = pps->weighted_bipred_idc; ++ pic->frame_mbs_only_flag = sps->frame_mbs_only_flag; ++ pic->transform_8x8_mode_flag = pps->transform_8x8_mode_flag; ++ pic->chroma_qp_index_offset = pps->chroma_qp_index_offset; ++ pic->second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; ++ pic->pic_init_qp_minus26 = pps->pic_init_qp_minus26; ++ pic->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; ++ pic->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; ++ pic->log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; ++ pic->pic_order_cnt_type = sps->pic_order_cnt_type; ++ pic->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; ++ pic->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; ++ pic->direct_8x8_inference_flag = sps->direct_8x8_inference_flag; ++ pic->entropy_coding_mode_flag = pps->entropy_coding_mode_flag; ++ pic->pic_order_present_flag = pps->pic_order_present_flag; ++ pic->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; ++ pic->redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; ++ ++ memcpy(pic->scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic->scaling_lists_4x4)); ++ memcpy(pic->scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic->scaling_lists_8x8)); ++ ++ /* set num_ref_frames to the number of actually available reference frames, ++ * if this is not set generation 3 decoders will fail. */ ++ /*pic->num_ref_frames =*/ ++ fill_vdpau_reference_list(&(this->nal_parser->dpb), pic->referenceFrames); ++ ++} ++ ++static int vdpau_decoder_init(video_decoder_t *this_gen) ++{ ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; ++ vo_frame_t *img; ++ ++ this->curr_pts = this->next_pts; ++ this->next_pts = 0; ++ ++ if(this->width == 0) { ++ this->width = this->nal_parser->current_nal->sps->pic_width; ++ this->height = this->nal_parser->current_nal->sps->pic_height; ++ } ++ ++ set_ratio(this_gen); ++ ++ _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width ); ++ _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height ); ++ _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*this->ratio) ); ++ _x_stream_info_set( this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step ); ++ _x_meta_info_set_utf8( this->stream, XINE_META_INFO_VIDEOCODEC, "H264/AVC (vdpau)" ); ++ xine_event_t event; ++ xine_format_change_data_t data; ++ event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; ++ event.stream = this->stream; ++ event.data = &data; ++ event.data_length = sizeof(data); ++ data.width = this->width; ++ data.height = this->height; ++ data.aspect = this->ratio; ++ xine_event_send( this->stream, &event ); ++ ++ switch(this->nal_parser->current_nal->sps->profile_idc) { ++ case 100: ++ this->profile = VDP_DECODER_PROFILE_H264_HIGH; ++ break; ++ case 77: ++ this->profile = VDP_DECODER_PROFILE_H264_MAIN; ++ break; ++ case 66: ++ default: ++ // nvidia's VDPAU doesn't support BASELINE. But most (every?) streams marked BASELINE do not use BASELINE specifics, ++ // so, just force MAIN. ++ //this->profile = VDP_DECODER_PROFILE_H264_BASELINE; ++ this->profile = VDP_DECODER_PROFILE_H264_MAIN; ++ break; ++ } ++ ++ // Level 4.1 limits: ++ int ref_frames = 0; ++ if(this->nal_parser->current_nal->sps->num_ref_frames) { ++ ref_frames = this->nal_parser->current_nal->sps->num_ref_frames; ++ } else { ++ uint32_t round_width = (this->width + 15) & ~15; ++ uint32_t round_height = (this->height + 15) & ~15; ++ uint32_t surf_size = (round_width * round_height * 3) / 2; ++ ref_frames = (12 * 1024 * 1024) / surf_size; ++ } ++ ++ if (ref_frames > 16) { ++ ref_frames = 16; ++ } ++ ++ printf("Allocate %d reference frames\n", ref_frames); ++ /* get the vdpau context from vo */ ++ //(this->stream->video_out->open) (this->stream->video_out, this->stream); ++ img = this->stream->video_out->get_frame (this->stream->video_out, ++ this->width, this->height, ++ this->ratio, ++ XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); ++ ++ img->duration = this->video_step; ++ img->pts = this->curr_pts; ++ ++ if (this->dangling_img) { ++ fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); ++ this->dangling_img->free(this->dangling_img); ++ } ++ this->dangling_img = img; ++ this->last_img = img; ++ ++ this->vdpau_accel = (vdpau_accel_t*)img->accel_data; ++ ++ /*VdpBool is_supported; ++ uint32_t max_level, max_references, max_width, max_height;*/ ++ if(this->vdpau_accel->vdp_runtime_nr > 0) { ++ xprintf(this->xine, XINE_VERBOSITY_LOG, ++ "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", ++ this->vdpau_accel->vdp_device, this->profile, this->width, this->height); ++ ++ VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, ++ this->profile, this->width, this->height, 16, &this->decoder); ++ ++ if(status != VDP_STATUS_OK) { ++ xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count) ++{ ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; ++ vo_frame_t *img = this->last_img; ++ ++ if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { ++ dpb_flush(&(this->nal_parser->dpb)); ++ } ++ ++ VdpPictureInfoH264 pic; ++ ++ fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); ++ ++ //printf("next decode: %d, %d\n", pic.field_order_cnt[0], pic.field_order_cnt[1]); ++ ++ if(!this->decoder_started && !pic.is_reference) ++ return 0; ++ ++ this->decoder_started = 1; ++ ++ struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; ++ struct slice_header *slc = this->nal_parser->current_nal->slc; ++ ++ if(sps->vui_parameters_present_flag && ++ sps->vui_parameters.timing_info_present_flag && ++ this->video_step == 0) { ++ this->video_step = 2*90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); ++ } ++ ++ /* flush the DPB if this frame was an IDR */ ++ //printf("is_idr: %d\n", this->nal_parser->is_idr); ++ this->nal_parser->is_idr = 0; ++ ++ /* go and decode a frame */ ++ ++ //dump_pictureinfo_h264(&pic); ++ ++ /*int i; ++ printf("Decode data: \n"); ++ for(i = 0; i < ((vdp_buffer->bitstream_bytes < 20) ? vdp_buffer->bitstream_bytes : 20); i++) { ++ printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); ++ if((i+1) % 10 == 0) ++ printf("\n"); ++ } ++ printf("\n...\n"); ++ for(i = vdp_buffer->bitstream_bytes - 20; i < vdp_buffer->bitstream_bytes; i++) { ++ printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); ++ if((i+1) % 10 == 0) ++ printf("\n"); ++ }*/ ++ ++ ++ if(img == NULL) { ++ img = this->stream->video_out->get_frame (this->stream->video_out, ++ this->width, this->height, ++ this->ratio, ++ XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); ++ this->vdpau_accel = (vdpau_accel_t*)img->accel_data; ++ ++ img->duration = this->video_step; ++ img->pts = this->curr_pts; ++ ++ if (this->dangling_img) { ++ fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); ++ this->dangling_img->free(this->dangling_img); ++ } ++ this->dangling_img = img; ++ } ++ ++ if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { ++ printf("VDPAU was preempted. Reinitialise the decoder.\n"); ++ this->decoder = VDP_INVALID_HANDLE; ++ vdpau_h264_reset(this_gen); ++ this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; ++ return 0; ++ } ++ ++ VdpVideoSurface surface = this->vdpau_accel->surface; ++ ++ //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer->bitstream_bytes, this->curr_pts); ++ VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, ++ surface, (VdpPictureInfo*)&pic, 1, vdp_buffer); ++ ++ /* only free the actual data, as the start seq is only ++ * locally allocated anyway. */ ++ if(((uint8_t*)vdp_buffer->bitstream) != NULL) { ++ free((uint8_t*)vdp_buffer->bitstream); ++ } ++ ++ this->curr_pts = this->next_pts; ++ this->next_pts = 0; ++ ++ process_mmc_operations(this->nal_parser); ++ ++ if(status != VDP_STATUS_OK) ++ { ++ xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); ++ if (this->dangling_img) ++ this->dangling_img->free(this->dangling_img); ++ img = this->last_img = this->dangling_img = NULL; ++ } ++ else { ++ img->bad_frame = 0; ++ ++ if((sps->vui_parameters_present_flag && ++ sps->vui_parameters.pic_struct_present_flag && ++ !this->nal_parser->current_nal->interlaced) || ++ (!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag)) ++ img->progressive_frame = 1; ++ else ++ img->progressive_frame = 0; ++ ++ if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic) ++ img->repeat_first_field = 1; ++ //else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) ++ // img->duration *= this->nal_parser->current_nal->repeat_pic; ++ ++ /* only bt601 and bt701 handled so far. others seem to be rarely used */ ++ if(sps->vui_parameters.colour_description_present) { ++ switch (sps->vui_parameters.colour_primaries) { ++ case 1: ++ this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709; ++ break; ++ case 5: ++ case 6: ++ default: ++ this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; ++ break; ++ } ++ } ++ ++ this->vdpau_accel->color_standard = this->color_standard; ++ ++ struct decoded_picture *decoded_pic = NULL; ++ if(pic.is_reference) { ++ if(!slc->field_pic_flag || !this->wait_for_bottom_field) { ++ decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); ++ this->last_ref_pic = decoded_pic; ++ decoded_pic->used_for_reference = 1; ++ dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); ++ this->dangling_img = NULL; ++ } else if(slc->field_pic_flag && this->wait_for_bottom_field) { ++ if(this->last_ref_pic) { ++ decoded_pic = this->last_ref_pic; ++ //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); ++ decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; ++ this->last_ref_pic->bottom_is_reference = 1; ++ } ++ } ++ } ++ ++ if(!slc->field_pic_flag || ++ (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { ++ ++ if(!decoded_pic) { ++ decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); ++ //decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; ++ dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); ++ this->dangling_img = NULL; ++ ++ if(decoded_pic->nal->slc->bottom_field_flag) ++ decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; ++ } ++ ++ decoded_pic->delayed_output = 1; ++ ++ if(this->wait_for_bottom_field && slc->bottom_field_flag) ++ decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; ++ ++ this->last_img = img = NULL; ++ ++ /* now retrieve the next output frame */ ++ if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 0)) != NULL) { ++ decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); ++ //printf("draw pts: %lld\n", decoded_pic->img->pts); ++ decoded_pic->img->draw(decoded_pic->img, this->stream); ++ dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); ++ } ++ ++ this->wait_for_bottom_field = 0; ++ ++ } else if(slc->field_pic_flag && !slc->bottom_field_flag) { ++ // don't draw yet, second field is missing. ++ this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; ++ this->wait_for_bottom_field = 1; ++ this->last_img = img; ++ } ++ } ++ ++ return 1; ++} ++ ++/* ++ * This function receives a buffer of data from the demuxer layer and ++ * figures out how to handle it based on its header flags. ++ */ ++static void vdpau_h264_decode_data (video_decoder_t *this_gen, ++ buf_element_t *buf) { ++ ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; ++ ++ VdpBitstreamBuffer vdp_buffer; ++ vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; ++ ++ /* a video decoder does not care about this flag (?) */ ++ if (buf->decoder_flags & BUF_FLAG_PREVIEW) ++ return; ++ ++ if(buf->decoder_flags & BUF_FLAG_FRAME_START || buf->decoder_flags & BUF_FLAG_FRAME_END) ++ this->have_frame_boundary_marks = 1; ++ ++ if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { ++ this->video_step = buf->decoder_info[0]; ++ _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); ++ } ++ ++ if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ ++ this->have_frame_boundary_marks = 0; ++ ++ xine_bmiheader *bih = (xine_bmiheader*)buf->content; ++ this->width = bih->biWidth; ++ this->height = bih->biHeight; ++ ++ uint8_t *codec_private = buf->content + sizeof(xine_bmiheader); ++ uint32_t codec_private_len = bih->biSize - sizeof(xine_bmiheader); ++ this->codec_private_len = codec_private_len; ++ this->codec_private = malloc(codec_private_len); ++ memcpy(this->codec_private, codec_private, codec_private_len); ++ ++ if(codec_private_len > 0) { ++ parse_codec_private(this->nal_parser, codec_private, codec_private_len); ++ } ++ } else if (buf->decoder_flags & BUF_FLAG_SPECIAL) { ++ this->have_frame_boundary_marks = 0; ++ ++ if(buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG) { ++ uint8_t *codec_private = buf->decoder_info_ptr[2]; ++ uint32_t codec_private_len = buf->decoder_info[2]; ++ this->codec_private_len = codec_private_len; ++ this->codec_private = malloc(codec_private_len); ++ memcpy(this->codec_private, codec_private, codec_private_len); ++ ++ if(codec_private_len > 0) { ++ parse_codec_private(this->nal_parser, codec_private, codec_private_len); ++ } ++ } else if (buf->decoder_info[1] == BUF_SPECIAL_PALETTE) { ++ printf("SPECIAL PALETTE is not yet handled\n"); ++ } else ++ printf("UNKNOWN SPECIAL HEADER\n"); ++ ++ } else { ++ /* parse the first nal packages to retrieve profile type */ ++ int len = 0; ++ uint32_t slice_count; ++ ++ while(len < buf->size && !(this->wait_for_frame_start && !(buf->decoder_flags & BUF_FLAG_FRAME_START))) { ++ this->wait_for_frame_start = 0; ++ len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, ++ (uint8_t*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); ++ ++ if(this->decoder == VDP_INVALID_HANDLE && ++ this->nal_parser->current_nal->sps != NULL && ++ this->nal_parser->current_nal->sps->pic_width > 0 && ++ this->nal_parser->current_nal->sps->pic_height > 0) { ++ ++ vdpau_decoder_init(this_gen); ++ } ++ ++ if(this->decoder != VDP_INVALID_HANDLE && ++ vdp_buffer.bitstream_bytes > 0 && ++ this->nal_parser->current_nal->slc != NULL && ++ this->nal_parser->current_nal->pps != NULL) { ++ vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); ++ } ++ ++ /* in case the last nal was detected as END_OF_SEQUENCE ++ * we will flush the dpb, so that all pictures get drawn ++ */ ++ if(this->nal_parser->last_nal_res == 3) ++ vdpau_h264_flush(this_gen); ++ } ++ ++ if(buf->pts != 0 && buf->pts != this->next_pts) { ++ //printf("next pts: %lld\n", buf->pts); ++ this->next_pts = buf->pts; ++ } ++ } ++ ++ if(buf->decoder_flags & BUF_FLAG_FRAME_END) ++ this->wait_for_frame_start = 0; ++} ++ ++/* ++ * This function is called when xine needs to flush the system. ++ */ ++static void vdpau_h264_flush (video_decoder_t *this_gen) { ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t*) this_gen; ++ struct decoded_picture *decoded_pic = NULL; ++ ++ while ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 1)) != NULL) { ++ decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); ++ printf("FLUSH draw pts: %lld\n", decoded_pic->img->pts); ++ decoded_pic->img->draw(decoded_pic->img, this->stream); ++ dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); ++ } ++} ++ ++/* ++ * This function resets the video decoder. ++ */ ++static void vdpau_h264_reset (video_decoder_t *this_gen) { ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; ++ ++ printf("vdpau_h264_reset\n"); ++ ++ dpb_free_all( &(this->nal_parser->dpb) ); ++ ++ if (this->decoder != VDP_INVALID_HANDLE) { ++ this->vdpau_accel->vdp_decoder_destroy( this->decoder ); ++ this->decoder = VDP_INVALID_HANDLE; ++ } ++ ++ free_parser(this->nal_parser); ++ ++ this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; ++ this->wait_for_bottom_field = 0; ++ this->video_step = 0; ++ this->curr_pts = 0; ++ this->next_pts = 0; ++ ++ this->nal_parser = init_parser(); ++ if(this->codec_private_len > 0) { ++ parse_codec_private(this->nal_parser, this->codec_private, this->codec_private_len); ++ ++ /* if the stream does not contain frame boundary marks we ++ * have to hope that the next nal will start with the next ++ * incoming buf... seems to work, though... ++ */ ++ this->wait_for_frame_start = this->have_frame_boundary_marks; ++ } ++ ++ if (this->dangling_img) { ++ this->dangling_img->free(this->dangling_img); ++ this->dangling_img = NULL; ++ } ++ ++ this->last_img = NULL; ++} ++ ++/* ++ * The decoder should forget any stored pts values here. ++ */ ++static void vdpau_h264_discontinuity (video_decoder_t *this_gen) { ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; ++ ++ this->curr_pts = 0; ++ this->next_pts = 0; ++ dpb_clear_all_pts(&this->nal_parser->dpb); ++} ++ ++/* ++ * This function frees the video decoder instance allocated to the decoder. ++ */ ++static void vdpau_h264_dispose (video_decoder_t *this_gen) { ++ ++ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; ++ ++ if (this->dangling_img) { ++ this->dangling_img->free(this->dangling_img); ++ this->dangling_img = NULL; ++ } ++ ++ dpb_free_all( &(this->nal_parser->dpb) ); ++ ++ if (this->decoder != VDP_INVALID_HANDLE) { ++ this->vdpau_accel->vdp_decoder_destroy( this->decoder ); ++ this->decoder = VDP_INVALID_HANDLE; ++ } ++ ++ this->stream->video_out->close( this->stream->video_out, this->stream ); ++ ++ free_parser (this->nal_parser); ++ free (this_gen); ++} ++ ++/* ++ * This function allocates, initializes, and returns a private video ++ * decoder structure. ++ */ ++static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { ++ ++ vdpau_h264_decoder_t *this ; ++ ++ /* the videoout must be vdpau-capable to support this decoder */ ++ if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) ++ return NULL; ++ ++ /* now check if vdpau has free decoder resource */ ++ vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); ++ vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; ++ int runtime_nr = accel->vdp_runtime_nr; ++ img->free(img); ++ VdpDecoder decoder; ++ VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_H264_MAIN, 1920, 1080, 16, &decoder ); ++ if ( st!=VDP_STATUS_OK ) { ++ lprintf( "can't create vdpau decoder.\n" ); ++ return 1; ++ } ++ ++ accel->vdp_decoder_destroy( decoder ); ++ ++ this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); ++ ++ this->video_decoder.decode_data = vdpau_h264_decode_data; ++ this->video_decoder.flush = vdpau_h264_flush; ++ this->video_decoder.reset = vdpau_h264_reset; ++ this->video_decoder.discontinuity = vdpau_h264_discontinuity; ++ this->video_decoder.dispose = vdpau_h264_dispose; ++ ++ this->stream = stream; ++ this->xine = stream->xine; ++ this->class = (vdpau_h264_class_t *) class_gen; ++ ++ this->decoder = VDP_INVALID_HANDLE; ++ this->vdp_runtime_nr = runtime_nr; ++ this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; ++ ++ this->nal_parser = init_parser(); ++ ++ (this->stream->video_out->open) (this->stream->video_out, this->stream); ++ ++ return &this->video_decoder; ++} ++ ++/* ++ * This function returns a brief string that describes (usually with the ++ * decoder's most basic name) the video decoder plugin. ++ */ ++static char *get_identifier (video_decoder_class_t *this) { ++ return "vdpau_h264"; ++} ++ ++/* ++ * This function returns a slightly longer string describing the video ++ * decoder plugin. ++ */ ++static char *get_description (video_decoder_class_t *this) { ++ return "vdpau_h264: h264 decoder plugin using VDPAU hardware decoding.\n" ++ "Must be used along with video_out_vdpau."; ++} ++ ++/* ++ * This function frees the video decoder class and any other memory that was ++ * allocated. ++ */ ++static void dispose_class (video_decoder_class_t *this) { ++ free (this); ++} ++ ++/* ++ * This function allocates a private video decoder class and initializes ++ * the class's member functions. ++ */ ++static void *init_plugin (xine_t *xine, void *data) { ++ ++ vdpau_h264_class_t *this; ++ ++ this = (vdpau_h264_class_t *) calloc(1, sizeof(vdpau_h264_class_t)); ++ ++ this->decoder_class.open_plugin = open_plugin; ++ this->decoder_class.get_identifier = get_identifier; ++ this->decoder_class.get_description = get_description; ++ this->decoder_class.dispose = dispose_class; ++ ++ return this; ++} ++ ++/* ++ * This is a list of all of the internal xine video buffer types that ++ * this decoder is able to handle. Check src/xine-engine/buffer.h for a ++ * list of valid buffer types (and add a new one if the one you need does ++ * not exist). Terminate the list with a 0. ++ */ ++static const uint32_t video_types[] = { ++ /* BUF_VIDEO_FOOVIDEO, */ ++ BUF_VIDEO_H264, ++ 0 ++}; ++ ++/* ++ * This data structure combines the list of supported xine buffer types and ++ * the priority that the plugin should be given with respect to other ++ * plugins that handle the same buffer type. A plugin with priority (n+1) ++ * will be used instead of a plugin with priority (n). ++ */ ++static const decoder_info_t dec_info_video = { ++ video_types, /* supported types */ ++ 7 /* priority */ ++}; ++ ++/* ++ * The plugin catalog entry. This is the only information that this plugin ++ * will export to the public. ++ */ ++const plugin_info_t xine_plugin_info[] EXPORTED = { ++ /* { type, API, "name", version, special_info, init_function } */ ++ { PLUGIN_VIDEO_DECODER, 18, "vdpau_h264", XINE_VERSION_CODE, &dec_info_video, init_plugin }, ++ { PLUGIN_NONE, 0, "", 0, NULL, NULL } ++}; +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/nal.c +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2008 Julian Scheel ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * nal.c: nal-structure utility functions ++ */ ++ ++#include ++#include ++#include ++ ++#include "nal.h" ++#include "xine_internal.h" ++ ++struct nal_unit* init_nal_unit() ++{ ++ struct nal_unit *nal = calloc(1, sizeof(struct nal_unit)); ++ ++ /*nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); ++ nal->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); ++ nal->slc = calloc(1, sizeof(struct slice_header));*/ ++ ++ return nal; ++} ++ ++void free_nal_unit(struct nal_unit *nal) ++{ ++ if(!nal) ++ return; ++ ++ free(nal->sps); ++ free(nal->pps); ++ free(nal->slc); ++ free(nal); ++} ++ ++void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) ++{ ++ /* size without pps, sps and slc units: */ ++ int size = sizeof(struct nal_unit) - sizeof(struct seq_parameter_set_rbsp*) ++ - sizeof(struct pic_parameter_set_rbsp*) - sizeof(struct slice_header*); ++ ++ xine_fast_memcpy(dest, src, size); ++ ++ if(!dest->sps) ++ dest->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); ++ ++ if(!dest->pps) ++ dest->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); ++ ++ if(!dest->slc) ++ dest->slc = calloc(1, sizeof(struct slice_header)); ++ ++ if(src->sps) ++ xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); ++ if(src->pps) ++ xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp)); ++ if(src->slc) ++ xine_fast_memcpy(dest->slc, src->slc, sizeof(struct slice_header)); ++} +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/vdpau_vc1.c +@@ -0,0 +1,1193 @@ ++/* ++ * Copyright (C) 2008 the xine project ++ * Copyright (C) 2008 Christophe Thommeret ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * vdpau_vc1.c, a vc1 video stream parser using VDPAU hardware decoder ++ * ++ */ ++ ++/*#define LOG*/ ++#define LOG_MODULE "vdpau_vc1" ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "xine_internal.h" ++#include "video_out.h" ++#include "buffer.h" ++#include "xineutils.h" ++#include "accel_vdpau.h" ++#include "bits_reader.h" ++ ++#include ++ ++#define sequence_header_code 0x0f ++#define sequence_end_code 0x0a ++#define entry_point_code 0x0e ++#define frame_start_code 0x0d ++#define field_start_code 0x0c ++#define slice_start_code 0x0b ++ ++#define PICTURE_FRAME 0 ++#define PICTURE_FRAME_INTERLACE 2 ++#define PICTURE_FIELD_INTERLACE 3 ++ ++#define I_FRAME 0 ++#define P_FRAME 1 ++#define B_FRAME 3 ++#define BI_FRAME 4 ++ ++#define FIELDS_I_I 0 ++#define FIELDS_I_P 1 ++#define FIELDS_P_I 2 ++#define FIELDS_P_P 3 ++#define FIELDS_B_B 4 ++#define FIELDS_B_BI 5 ++#define FIELDS_BI_B 6 ++#define FIELDS_BI_BI 7 ++ ++#define MODE_STARTCODE 0 ++#define MODE_FRAME 1 ++ ++/*#define MAKE_DAT*/ /*do NOT define this, unless you know what you do */ ++#ifdef MAKE_DAT ++static int nframes; ++static FILE *outfile; ++#endif ++ ++ ++ ++const double aspect_ratio[] = { ++ 0.0, ++ 1.0, ++ 12./11., ++ 10./11., ++ 16./11., ++ 40./33., ++ 24./11., ++ 20./11., ++ 32./11., ++ 80./33., ++ 18./11., ++ 15./11., ++ 64./33., ++ 160./99. ++}; ++ ++ ++ ++typedef struct { ++ VdpPictureInfoVC1 vdp_infos; ++ int slices; ++ int fptype; ++ int field; ++ int header_size; ++ int hrd_param_flag; ++ int hrd_num_leaky_buckets; ++ int repeat_first_field; ++ int top_field_first; ++ int skipped; ++} picture_t; ++ ++ ++ ++typedef struct { ++ uint32_t coded_width; ++ uint32_t coded_height; ++ ++ uint64_t video_step; /* frame duration in pts units */ ++ double ratio; ++ VdpDecoderProfile profile; ++ ++ int mode; ++ int have_header; ++ ++ uint8_t *buf; /* accumulate data */ ++ int bufseek; ++ int start; ++ int code_start, current_code; ++ uint32_t bufsize; ++ uint32_t bufpos; ++ ++ picture_t picture; ++ vo_frame_t *forward_ref; ++ vo_frame_t *backward_ref; ++ ++ int64_t seq_pts; ++ int64_t cur_pts; ++ ++ vdpau_accel_t *accel_vdpau; ++ ++ bits_reader_t br; ++ ++ int vdp_runtime_nr; ++ ++} sequence_t; ++ ++ ++ ++typedef struct { ++ video_decoder_class_t decoder_class; ++} vdpau_vc1_class_t; ++ ++ ++ ++typedef struct vdpau_vc1_decoder_s { ++ video_decoder_t video_decoder; /* parent video decoder structure */ ++ ++ vdpau_vc1_class_t *class; ++ xine_stream_t *stream; ++ ++ sequence_t sequence; ++ ++ VdpDecoder decoder; ++ VdpDecoderProfile decoder_profile; ++ uint32_t decoder_width; ++ uint32_t decoder_height; ++ ++} vdpau_vc1_decoder_t; ++ ++ ++ ++static void init_picture( picture_t *pic ) ++{ ++ memset( pic, 0, sizeof( picture_t ) ); ++} ++ ++ ++ ++static void reset_picture( picture_t *pic ) ++{ ++ pic->slices = 1; ++} ++ ++ ++ ++static void reset_sequence( sequence_t *sequence ) ++{ ++ lprintf( "reset_sequence\n" ); ++ sequence->bufpos = 0; ++ sequence->bufseek = 0; ++ sequence->start = -1; ++ sequence->code_start = sequence->current_code = 0; ++ sequence->seq_pts = sequence->cur_pts = 0; ++ if ( sequence->forward_ref ) ++ sequence->forward_ref->free( sequence->forward_ref ); ++ sequence->forward_ref = NULL; ++ if ( sequence->backward_ref ) ++ sequence->backward_ref->free( sequence->backward_ref ); ++ sequence->backward_ref = NULL; ++ reset_picture( &sequence->picture ); ++} ++ ++ ++ ++static void init_sequence( sequence_t *sequence ) ++{ ++ lprintf( "init_sequence\n" ); ++ sequence->have_header = 0; ++ sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; ++ sequence->ratio = 0; ++ sequence->video_step = 0; ++ sequence->picture.hrd_param_flag = 0; ++ reset_sequence( sequence ); ++} ++ ++ ++ ++static void update_metadata( vdpau_vc1_decoder_t *this_gen ) ++{ ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ ++ if ( !sequence->have_header ) { ++ sequence->have_header = 1; ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); ++ _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" ); ++ xine_event_t event; ++ xine_format_change_data_t data; ++ event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; ++ event.stream = this_gen->stream; ++ event.data = &data; ++ event.data_length = sizeof(data); ++ data.width = sequence->coded_width; ++ data.height = sequence->coded_height; ++ data.aspect = sequence->ratio; ++ xine_event_send( this_gen->stream, &event ); ++ } ++} ++ ++ ++ ++static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ lprintf( "sequence_header_advanced\n" ); ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ ++ if ( len < 5 ) ++ return; ++ ++ sequence->profile = VDP_DECODER_PROFILE_VC1_ADVANCED; ++ lprintf("VDP_DECODER_PROFILE_VC1_ADVANCED\n"); ++ bits_reader_set( &sequence->br, buf ); ++ read_bits( &sequence->br, 15 ); ++ sequence->picture.vdp_infos.postprocflag = read_bits( &sequence->br, 1 ); ++ sequence->coded_width = read_bits( &sequence->br, 12 )<<1; ++ sequence->coded_height = (read_bits( &sequence->br, 12 )+1)<<1; ++ sequence->picture.vdp_infos.pulldown = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.interlace = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.tfcntrflag = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.finterpflag = read_bits( &sequence->br, 1 ); ++ read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.psf = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.maxbframes = 7; ++ if ( read_bits( &sequence->br, 1 ) ) { ++ double w, h; ++ int ar=0; ++ w = read_bits( &sequence->br, 14 )+1; ++ h = read_bits( &sequence->br, 14 )+1; ++ if ( read_bits( &sequence->br, 1 ) ) { ++ ar = read_bits( &sequence->br, 4 ); ++ } ++ if ( ar==15 ) { ++ w = read_bits( &sequence->br, 8 ); ++ h = read_bits( &sequence->br, 8 ); ++ sequence->ratio = w/h; ++ lprintf("aspect_ratio (w/h) = %f\n", sequence->ratio); ++ } ++ else if ( ar && ar<14 ) { ++ sequence->ratio = sequence->coded_width*aspect_ratio[ar]/sequence->coded_height; ++ lprintf("aspect_ratio = %f\n", sequence->ratio); ++ } ++ ++ if ( read_bits( &sequence->br, 1 ) ) { ++ if ( read_bits( &sequence->br, 1 ) ) { ++ int exp = read_bits( &sequence->br, 16 ); ++ lprintf("framerate exp = %d\n", exp); ++ } ++ else { ++ double nr = read_bits( &sequence->br, 8 ); ++ switch ((int)nr) { ++ case 1: nr = 24000; break; ++ case 2: nr = 25000; break; ++ case 3: nr = 30000; break; ++ case 4: nr = 50000; break; ++ case 5: nr = 60000; break; ++ default: nr = 0; ++ } ++ double dr = read_bits( &sequence->br, 4 ); ++ switch ((int)dr) { ++ case 2: dr = 1001; break; ++ default: dr = 1000; ++ } ++ sequence->video_step = 90000/(nr/dr); ++ lprintf("framerate = %f video_step = %d\n", nr/dr, sequence->video_step); ++ } ++ } ++ if ( read_bits( &sequence->br, 1 ) ) { ++ int col = read_bits( &sequence->br, 8 ); ++ lprintf("color_standard = %d\n", col); ++ read_bits( &sequence->br, 16 ); ++ } ++ } ++ sequence->picture.hrd_param_flag = read_bits( &sequence->br, 1 ); ++ if ( sequence->picture.hrd_param_flag ) ++ sequence->picture.hrd_num_leaky_buckets = read_bits( &sequence->br, 5 ); ++ ++ update_metadata( this_gen ); ++} ++ ++ ++ ++static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ lprintf( "sequence_header\n" ); ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ ++ if ( len < 4 ) ++ return; ++ ++ bits_reader_set( &sequence->br, buf ); ++ switch ( read_bits( &sequence->br, 2 ) ) { ++ case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; lprintf("VDP_DECODER_PROFILE_VC1_SIMPLE\n"); break; ++ case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("VDP_DECODER_PROFILE_VC1_MAIN\n"); break; ++ case 2: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("vc1_complex profile not supported by vdpau, trying vc1_main.\n"); break; ++ case 3: return sequence_header_advanced( this_gen, buf, len ); break; ++ default: return; /* illegal value, broken header? */ ++ } ++ read_bits( &sequence->br, 10 ); ++ sequence->picture.vdp_infos.loopfilter = read_bits( &sequence->br, 1 ); ++ read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.multires = read_bits( &sequence->br, 1 ); ++ read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.fastuvmc = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.extended_mv = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.dquant = read_bits( &sequence->br, 2 ); ++ sequence->picture.vdp_infos.vstransform = read_bits( &sequence->br, 1 ); ++ read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.overlap = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.syncmarker = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.rangered = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.maxbframes = read_bits( &sequence->br, 3 ); ++ sequence->picture.vdp_infos.quantizer = read_bits( &sequence->br, 2 ); ++ sequence->picture.vdp_infos.finterpflag = read_bits( &sequence->br, 1 ); ++ ++ update_metadata( this_gen ); ++} ++ ++ ++ ++static void entry_point( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ lprintf( "entry_point\n" ); ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ ++ bits_reader_set( &sequence->br, buf ); ++ read_bits( &sequence->br, 2 ); ++ sequence->picture.vdp_infos.panscan_flag = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.refdist_flag = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.loopfilter = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.fastuvmc = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.extended_mv = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.dquant = read_bits( &sequence->br, 2 ); ++ sequence->picture.vdp_infos.vstransform = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.overlap = read_bits( &sequence->br, 1 ); ++ sequence->picture.vdp_infos.quantizer = read_bits( &sequence->br, 2 ); ++ ++ if ( sequence->picture.hrd_param_flag ) { ++ int i; ++ for ( i=0; ipicture.hrd_num_leaky_buckets; ++i ) ++ read_bits( &sequence->br, 8 ); ++ } ++ ++ if ( read_bits( &sequence->br, 1 ) ) { ++ sequence->coded_width = (read_bits( &sequence->br, 12 )+1)<<1; ++ sequence->coded_height = (read_bits( &sequence->br, 12 )+1)<<1; ++ } ++ ++ if ( sequence->picture.vdp_infos.extended_mv ) ++ sequence->picture.vdp_infos.extended_dmv = read_bits( &sequence->br, 1 ); ++ ++ sequence->picture.vdp_infos.range_mapy_flag = read_bits( &sequence->br, 1 ); ++ if ( sequence->picture.vdp_infos.range_mapy_flag ) { ++ sequence->picture.vdp_infos.range_mapy = read_bits( &sequence->br, 3 ); ++ } ++ sequence->picture.vdp_infos.range_mapuv_flag = read_bits( &sequence->br, 1 ); ++ if ( sequence->picture.vdp_infos.range_mapuv_flag ) { ++ sequence->picture.vdp_infos.range_mapuv = read_bits( &sequence->br, 3 ); ++ } ++} ++ ++ ++ ++static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ picture_t *pic = (picture_t*)&sequence->picture; ++ VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); ++ int tmp; ++ ++ lprintf("picture_header\n"); ++ ++ bits_reader_set( &sequence->br, buf ); ++ read_bits( &sequence->br, 2 ); ++ ++ if ( info->finterpflag ) ++ read_bits( &sequence->br, 1 ); ++ if ( info->rangered ) { ++ /*info->rangered &= ~2; ++ info->rangered |= get_bits( buf,off++,1 ) << 1;*/ ++ info->rangered = (read_bits( &sequence->br, 1 ) << 1) +1; ++ } ++ if ( !info->maxbframes ) { ++ if ( read_bits( &sequence->br, 1 ) ) ++ info->picture_type = P_FRAME; ++ else ++ info->picture_type = I_FRAME; ++ } ++ else { ++ if ( read_bits( &sequence->br, 1 ) ) ++ info->picture_type = P_FRAME; ++ else { ++ if ( read_bits( &sequence->br, 1 ) ) ++ info->picture_type = I_FRAME; ++ else ++ info->picture_type = B_FRAME; ++ } ++ } ++ if ( info->picture_type == B_FRAME ) { ++ tmp = read_bits( &sequence->br, 3 ); ++ if ( tmp==7 ) { ++ tmp = (tmp<<4) | read_bits( &sequence->br, 4 ); ++ if ( tmp==127 ) ++ info->picture_type = BI_FRAME; ++ } ++ } ++} ++ ++ ++ ++static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ picture_t *pic = (picture_t*)&sequence->picture; ++ VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); ++ ++ lprintf("picture_header_advanced\n"); ++ ++ bits_reader_set( &sequence->br, buf ); ++ ++ if ( info->interlace ) { ++ lprintf("frame->interlace=1\n"); ++ if ( !read_bits( &sequence->br, 1 ) ) { ++ lprintf("progressive frame\n"); ++ info->frame_coding_mode = PICTURE_FRAME; ++ } ++ else { ++ if ( !read_bits( &sequence->br, 1 ) ) { ++ lprintf("frame interlaced\n"); ++ info->frame_coding_mode = PICTURE_FRAME_INTERLACE; ++ } ++ else { ++ lprintf("field interlaced\n"); ++ info->frame_coding_mode = PICTURE_FIELD_INTERLACE; ++ } ++ } ++ } ++ if ( info->interlace && info->frame_coding_mode == PICTURE_FIELD_INTERLACE ) { ++ pic->fptype = read_bits( &sequence->br, 3 ); ++ switch ( pic->fptype ) { ++ case FIELDS_I_I: ++ case FIELDS_I_P: ++ info->picture_type = I_FRAME; break; ++ case FIELDS_P_I: ++ case FIELDS_P_P: ++ info->picture_type = P_FRAME; break; ++ case FIELDS_B_B: ++ case FIELDS_B_BI: ++ info->picture_type = B_FRAME; break; ++ default: ++ info->picture_type = BI_FRAME; ++ } ++ } ++ else { ++ if ( !read_bits( &sequence->br, 1 ) ) ++ info->picture_type = P_FRAME; ++ else { ++ if ( !read_bits( &sequence->br, 1 ) ) ++ info->picture_type = B_FRAME; ++ else { ++ if ( !read_bits( &sequence->br, 1 ) ) ++ info->picture_type = I_FRAME; ++ else { ++ if ( !read_bits( &sequence->br, 1 ) ) ++ info->picture_type = BI_FRAME; ++ else { ++ info->picture_type = P_FRAME; ++ pic->skipped = 1; ++ } ++ } ++ } ++ } ++ } ++ if ( info->tfcntrflag ) { ++ lprintf("tfcntrflag=1\n"); ++ read_bits( &sequence->br, 8 ); ++ } ++ if ( info->pulldown && info->interlace ) { ++ pic->top_field_first = read_bits( &sequence->br, 1 ); ++ pic->repeat_first_field = read_bits( &sequence->br, 1 ); ++ } ++} ++ ++ ++ ++static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ int off=0; ++ ++ while ( off < (len-4) ) { ++ uint8_t *buffer = buf+off; ++ if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { ++ switch ( buffer[3] ) { ++ case sequence_header_code: sequence_header( this_gen, buf+off+4, len-off-4 ); break; ++ case entry_point_code: entry_point( this_gen, buf+off+4, len-off-4 ); break; ++ } ++ } ++ ++off; ++ } ++ if ( !sequence->have_header ) ++ sequence_header( this_gen, buf, len ); ++} ++ ++ ++ ++static void remove_emulation_prevention( uint8_t *src, uint8_t *dst, int src_len, int *dst_len ) ++{ ++ int i; ++ int len = 0; ++ int removed = 0; ++ ++ for ( i=0; isequence; ++ ++ if ( !sequence->have_header && buf[3]!=sequence_header_code ) ++ return 0; ++ ++ if ( sequence->code_start == frame_start_code ) { ++ if ( sequence->current_code==field_start_code || sequence->current_code==slice_start_code ) { ++ sequence->picture.slices++; ++ return -1; ++ } ++ return 1; /* frame complete, decode */ ++ } ++ ++ switch ( buf[3] ) { ++ int dst_len; ++ uint8_t *tmp; ++ case sequence_header_code: ++ lprintf("sequence_header_code\n"); ++ tmp = malloc( len ); ++ remove_emulation_prevention( buf, tmp, len, &dst_len ); ++ sequence_header( this_gen, tmp+4, dst_len-4 ); ++ free( tmp ); ++ break; ++ case entry_point_code: ++ lprintf("entry_point_code\n"); ++ tmp = malloc( len ); ++ remove_emulation_prevention( buf, tmp, len, &dst_len ); ++ entry_point( this_gen, tmp+4, dst_len-4 ); ++ free( tmp ); ++ break; ++ case sequence_end_code: ++ lprintf("sequence_end_code\n"); ++ break; ++ case frame_start_code: ++ lprintf("frame_start_code, len=%d\n", len); ++ break; ++ case field_start_code: ++ lprintf("field_start_code\n"); ++ break; ++ case slice_start_code: ++ lprintf("slice_start_code, len=%d\n", len); ++ break; ++ } ++ return 0; ++} ++ ++ ++ ++static void duplicate_image( vdpau_vc1_decoder_t *vd, vo_frame_t *dst ) ++{ ++ lprintf("duplicate_image\n"); ++ sequence_t *seq = (sequence_t*)&vd->sequence; ++ picture_t *pic = (picture_t*)&seq->picture; ++ ++ if ( !seq->backward_ref ) /* Should not happen! */ ++ return; ++ ++ dst->proc_duplicate_frame_data( dst, seq->backward_ref ); ++} ++ ++ ++ ++static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_t *buf, int len ) ++{ ++ sequence_t *seq = (sequence_t*)&vd->sequence; ++ picture_t *pic = (picture_t*)&seq->picture; ++ ++ VdpStatus st; ++ if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) { ++ if ( vd->decoder!=VDP_INVALID_HANDLE ) { ++ accel->vdp_decoder_destroy( vd->decoder ); ++ vd->decoder = VDP_INVALID_HANDLE; ++ } ++ st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); ++ if ( st!=VDP_STATUS_OK ) ++ printf( "vdpau_vc1: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); ++ else { ++ lprintf( "decoder created.\n" ); ++ vd->decoder_profile = seq->profile; ++ vd->decoder_width = seq->coded_width; ++ vd->decoder_height = seq->coded_height; ++ seq->vdp_runtime_nr = accel->vdp_runtime_nr; ++ } ++ } ++ ++ VdpBitstreamBuffer vbit; ++ vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; ++ vbit.bitstream = buf; ++ vbit.bitstream_bytes = len; ++ if ( pic->field ) ++ vbit.bitstream_bytes = pic->field; ++ st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); ++ if ( st!=VDP_STATUS_OK ) ++ printf( "vdpau_vc1: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); ++ else { ++ lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", ++ pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); ++ } ++ VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); ++ lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->slice_count, info->picture_type, info->frame_coding_mode, ++ info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, ++ info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, ++ info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); ++ ++ if ( pic->field ) { ++ int old_type = pic->vdp_infos.picture_type; ++ switch ( pic->fptype ) { ++ case FIELDS_I_I: ++ case FIELDS_P_I: ++ pic->vdp_infos.picture_type = I_FRAME; ++ pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; ++ pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; ++ break; ++ case FIELDS_I_P: ++ case FIELDS_P_P: ++ pic->vdp_infos.forward_reference = accel->surface; ++ pic->vdp_infos.picture_type = P_FRAME; break; ++ case FIELDS_B_B: ++ case FIELDS_BI_B: ++ pic->vdp_infos.picture_type = B_FRAME; ++ break; ++ default: ++ pic->vdp_infos.picture_type = BI_FRAME; ++ } ++ vbit.bitstream = buf+pic->field+4; ++ vbit.bitstream_bytes = len-pic->field-4; ++ st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); ++ if ( st!=VDP_STATUS_OK ) ++ printf( "vdpau_vc1: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); ++ else { ++ lprintf( "DECODER SUCCESS (second field): slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", ++ pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); ++ } ++ VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); ++ lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->slice_count, info->picture_type, info->frame_coding_mode, ++ info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, ++ info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, ++ info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); ++ ++ pic->vdp_infos.picture_type = old_type; ++ } ++} ++ ++ ++ ++static int search_field( vdpau_vc1_decoder_t *vd, uint8_t *buf, int len ) ++{ ++ int i; ++ lprintf("search_fields, len=%d\n", len); ++ for ( i=0; isequence; ++ picture_t *pic = (picture_t*)&seq->picture; ++ vdpau_accel_t *ref_accel; ++ int field; ++ ++ uint8_t *buf; ++ int len; ++ ++ pic->skipped = 0; ++ pic->field = 0; ++ ++ if ( seq->mode == MODE_FRAME ) { ++ buf = seq->buf; ++ len = seq->bufpos; ++ if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) ++ picture_header_advanced( vd, buf, len ); ++ else ++ picture_header( vd, buf, len ); ++ ++ if ( len < 2 ) ++ pic->skipped = 1; ++ } ++ else { ++ seq->picture.vdp_infos.slice_count = seq->picture.slices; ++ buf = seq->buf+seq->start+4; ++ len = seq->bufseek-seq->start-4; ++ if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) { ++ int tmplen = (len>50) ? 50 : len; ++ uint8_t *tmp = malloc( tmplen ); ++ remove_emulation_prevention( buf, tmp, tmplen, &tmplen ); ++ picture_header_advanced( vd, tmp, tmplen ); ++ free( tmp ); ++ } ++ else ++ picture_header( vd, buf, len ); ++ ++ if ( len < 2 ) ++ pic->skipped = 1; ++ } ++ ++ if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode == PICTURE_FIELD_INTERLACE ) { ++ if ( !(field = search_field( vd, buf, len )) ) ++ lprintf("error, no fields found!\n"); ++ else ++ pic->field = field; ++ } ++ ++ pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; ++ pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; ++ ++ if ( pic->vdp_infos.picture_type==P_FRAME ) { ++ if ( seq->backward_ref ) { ++ ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; ++ pic->vdp_infos.forward_reference = ref_accel->surface; ++ } ++ else { ++ reset_picture( &seq->picture ); ++ return; ++ } ++ } ++ else if ( pic->vdp_infos.picture_type>=B_FRAME ) { ++ if ( seq->forward_ref ) { ++ ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; ++ pic->vdp_infos.forward_reference = ref_accel->surface; ++ } ++ else { ++ reset_picture( &seq->picture ); ++ return; ++ } ++ if ( seq->backward_ref ) { ++ ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; ++ pic->vdp_infos.backward_reference = ref_accel->surface; ++ } ++ else { ++ reset_picture( &seq->picture ); ++ return; ++ } ++ } ++ ++ vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, ++ seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); ++ vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; ++ if ( !seq->accel_vdpau ) ++ seq->accel_vdpau = accel; ++ ++ if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) { ++ seq->accel_vdpau = accel; ++ if ( seq->forward_ref ) ++ seq->forward_ref->free( seq->forward_ref ); ++ seq->forward_ref = NULL; ++ if ( seq->backward_ref ) ++ seq->backward_ref->free( seq->backward_ref ); ++ seq->backward_ref = NULL; ++ vd->decoder = VDP_INVALID_HANDLE; ++ } ++ ++ if ( pic->skipped ) ++ duplicate_image( vd, img ); ++ else ++ decode_render( vd, accel, buf, len ); ++ ++ ++#ifdef MAKE_DAT ++ if ( nframes==0 ) { ++ fwrite( &seq->coded_width, 1, sizeof(seq->coded_width), outfile ); ++ fwrite( &seq->coded_height, 1, sizeof(seq->coded_height), outfile ); ++ fwrite( &seq->ratio, 1, sizeof(seq->ratio), outfile ); ++ fwrite( &seq->profile, 1, sizeof(seq->profile), outfile ); ++ } ++ ++ if ( nframes++ < 25 ) { ++ fwrite( &pic->vdp_infos, 1, sizeof(pic->vdp_infos), outfile ); ++ fwrite( &len, 1, sizeof(len), outfile ); ++ fwrite( buf, 1, len, outfile ); ++ printf( "picture_type = %d\n", pic->vdp_infos.picture_type); ++ } ++#endif ++ ++ if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode ) { ++ img->progressive_frame = 0; ++ img->top_field_first = pic->top_field_first; ++ } ++ else { ++ img->progressive_frame = 1; ++ img->top_field_first = 1; ++ } ++ img->pts = seq->seq_pts; ++ img->bad_frame = 0; ++ img->duration = seq->video_step; ++ accel->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709; ++ ++ if ( pic->vdp_infos.picture_typevdp_infos.picture_type==I_FRAME && !seq->backward_ref ) { ++ img->pts = 0; ++ img->draw( img, vd->stream ); ++ ++img->drawn; ++ } ++ if ( seq->forward_ref ) { ++ seq->forward_ref->drawn = 0; ++ seq->forward_ref->free( seq->forward_ref ); ++ } ++ seq->forward_ref = seq->backward_ref; ++ if ( seq->forward_ref && !seq->forward_ref->drawn ) { ++ seq->forward_ref->draw( seq->forward_ref, vd->stream ); ++ } ++ seq->backward_ref = img; ++ } ++ else { ++ img->draw( img, vd->stream ); ++ img->free( img ); ++ } ++ ++ seq->seq_pts +=seq->video_step; ++ ++ reset_picture( &seq->picture ); ++} ++ ++ ++ ++/* ++ * This function receives a buffer of data from the demuxer layer and ++ * figures out how to handle it based on its header flags. ++ */ ++static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf) ++{ ++ vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; ++ sequence_t *seq = (sequence_t*)&this->sequence; ++ ++ /* a video decoder does not care about this flag (?) */ ++ if (buf->decoder_flags & BUF_FLAG_PREVIEW) { ++ lprintf("BUF_FLAG_PREVIEW\n"); ++ } ++ ++ if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { ++ lprintf("BUF_FLAG_FRAMERATE=%d\n", buf->decoder_info[0]); ++ if ( buf->decoder_info[0] > 0 ) { ++ this->sequence.video_step = buf->decoder_info[0]; ++ _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->sequence.video_step); ++ } ++ } ++ ++ if (buf->decoder_flags & BUF_FLAG_HEADER) { ++ lprintf("BUF_FLAG_HEADER\n"); ++ } ++ ++ if (buf->decoder_flags & BUF_FLAG_ASPECT) { ++ lprintf("BUF_FLAG_ASPECT\n"); ++ seq->ratio = (double)buf->decoder_info[1]/(double)buf->decoder_info[2]; ++ lprintf("arx=%d ary=%d ratio=%f\n", buf->decoder_info[1], buf->decoder_info[2], seq->ratio); ++ } ++ ++ if (buf->decoder_flags & BUF_FLAG_FRAME_START) { ++ lprintf("BUF_FLAG_FRAME_START\n"); ++ seq->seq_pts = buf->pts; ++ } ++ ++ if ( !buf->size ) ++ return; ++ ++ seq->cur_pts = buf->pts; ++ ++ if (buf->decoder_flags & BUF_FLAG_STDHEADER) { ++ lprintf("BUF_FLAG_STDHEADER\n"); ++ xine_bmiheader *bih = (xine_bmiheader *) buf->content; ++ int bs = sizeof( xine_bmiheader ); ++ seq->coded_width = bih->biWidth; ++ seq->coded_height = bih->biHeight; ++ lprintf( "width=%d height=%d\n", bih->biWidth, bih->biHeight ); ++ if ( buf->size > bs ) { ++ seq->mode = MODE_FRAME; ++ parse_header( this, buf->content+bs, buf->size-bs ); ++ } ++ return; ++ } ++ ++ int size = seq->bufpos+buf->size; ++ if ( seq->bufsize < size ) { ++ seq->bufsize = size+10000; ++ seq->buf = realloc( seq->buf, seq->bufsize ); ++ lprintf("sequence buffer realloced = %d\n", seq->bufsize ); ++ } ++ xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); ++ seq->bufpos += buf->size; ++ ++ if ( seq->mode == MODE_FRAME ) { ++ if (buf->decoder_flags & BUF_FLAG_FRAME_END) { ++ lprintf("BUF_FLAG_FRAME_END\n"); ++ seq->picture.vdp_infos.slice_count = 1; ++ decode_picture( this ); ++ seq->bufpos = 0; ++ } ++ } ++ else { ++ int res; ++ while ( seq->bufseek <= seq->bufpos-4 ) { ++ uint8_t *buffer = seq->buf+seq->bufseek; ++ if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { ++ seq->current_code = buffer[3]; ++ lprintf("current_code = %d\n", seq->current_code); ++ if ( seq->start<0 ) { ++ seq->start = seq->bufseek; ++ seq->code_start = buffer[3]; ++ lprintf("code_start = %d\n", seq->code_start); ++ if ( seq->cur_pts ) ++ seq->seq_pts = seq->cur_pts; ++ } ++ else { ++ res = parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ); ++ if ( res==1 ) { ++ decode_picture( this ); ++ parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ); ++ } ++ if ( res!=-1 ) { ++ uint8_t *tmp = (uint8_t*)malloc(seq->bufsize); ++ xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek ); ++ seq->bufpos -= seq->bufseek; ++ seq->start = -1; ++ seq->bufseek = -1; ++ free( seq->buf ); ++ seq->buf = tmp; ++ } ++ } ++ } ++ ++seq->bufseek; ++ } ++ } ++} ++ ++ ++ ++/* ++ * This function is called when xine needs to flush the system. ++ */ ++static void vdpau_vc1_flush (video_decoder_t *this_gen) { ++ vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_vc1_flush\n" ); ++} ++ ++/* ++ * This function resets the video decoder. ++ */ ++static void vdpau_vc1_reset (video_decoder_t *this_gen) { ++ vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_vc1_reset\n" ); ++ reset_sequence( &this->sequence ); ++} ++ ++/* ++ * The decoder should forget any stored pts values here. ++ */ ++static void vdpau_vc1_discontinuity (video_decoder_t *this_gen) { ++ vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_vc1_discontinuity\n" ); ++} ++ ++/* ++ * This function frees the video decoder instance allocated to the decoder. ++ */ ++static void vdpau_vc1_dispose (video_decoder_t *this_gen) { ++ ++ vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_vc1_dispose\n" ); ++ ++ if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) { ++ this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder ); ++ this->decoder = VDP_INVALID_HANDLE; ++ } ++ ++ reset_sequence( &this->sequence ); ++ ++ this->stream->video_out->close( this->stream->video_out, this->stream ); ++ ++ free( this->sequence.buf ); ++ free( this_gen ); ++} ++ ++/* ++ * This function allocates, initializes, and returns a private video ++ * decoder structure. ++ */ ++static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { ++ ++ vdpau_vc1_decoder_t *this ; ++ ++ lprintf( "open_plugin\n" ); ++ ++ /* the videoout must be vdpau-capable to support this decoder */ ++ if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_VC1) ) ++ return NULL; ++ ++ /* now check if vdpau has free decoder resource */ ++ vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); ++ vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; ++ int runtime_nr = accel->vdp_runtime_nr; ++ img->free(img); ++ VdpDecoder decoder; ++ VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, 1920, 1080, 2, &decoder ); ++ if ( st!=VDP_STATUS_OK ) { ++ lprintf( "can't create vdpau decoder.\n" ); ++ return 1; ++ } ++ ++ accel->vdp_decoder_destroy( decoder ); ++ ++ this = (vdpau_vc1_decoder_t *) calloc(1, sizeof(vdpau_vc1_decoder_t)); ++ ++ this->video_decoder.decode_data = vdpau_vc1_decode_data; ++ this->video_decoder.flush = vdpau_vc1_flush; ++ this->video_decoder.reset = vdpau_vc1_reset; ++ this->video_decoder.discontinuity = vdpau_vc1_discontinuity; ++ this->video_decoder.dispose = vdpau_vc1_dispose; ++ ++ this->stream = stream; ++ this->class = (vdpau_vc1_class_t *) class_gen; ++ ++ this->sequence.bufsize = 10000; ++ this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); ++ this->sequence.forward_ref = 0; ++ this->sequence.backward_ref = 0; ++ this->sequence.vdp_runtime_nr = runtime_nr; ++ init_sequence( &this->sequence ); ++ ++ init_picture( &this->sequence.picture ); ++ ++ this->decoder = VDP_INVALID_HANDLE; ++ this->sequence.accel_vdpau = NULL; ++ this->sequence.mode = MODE_STARTCODE; ++ ++ (stream->video_out->open)(stream->video_out, stream); ++ ++#ifdef MAKE_DAT ++ outfile = fopen( "/tmp/vc1.dat","w"); ++ nframes = 0; ++#endif ++ ++ return &this->video_decoder; ++} ++ ++/* ++ * This function returns a brief string that describes (usually with the ++ * decoder's most basic name) the video decoder plugin. ++ */ ++static char *get_identifier (video_decoder_class_t *this) { ++ return "vdpau_vc1"; ++} ++ ++/* ++ * This function returns a slightly longer string describing the video ++ * decoder plugin. ++ */ ++static char *get_description (video_decoder_class_t *this) { ++ return "vdpau_vc1: vc1 decoder plugin using VDPAU hardware decoding.\n" ++ "Must be used along with video_out_vdpau."; ++} ++ ++/* ++ * This function frees the video decoder class and any other memory that was ++ * allocated. ++ */ ++static void dispose_class (video_decoder_class_t *this) { ++ free (this); ++} ++ ++/* ++ * This function allocates a private video decoder class and initializes ++ * the class's member functions. ++ */ ++static void *init_plugin (xine_t *xine, void *data) { ++ ++ vdpau_vc1_class_t *this; ++ ++ this = (vdpau_vc1_class_t *) calloc(1, sizeof(vdpau_vc1_class_t)); ++ ++ this->decoder_class.open_plugin = open_plugin; ++ this->decoder_class.get_identifier = get_identifier; ++ this->decoder_class.get_description = get_description; ++ this->decoder_class.dispose = dispose_class; ++ ++ return this; ++} ++ ++/* ++ * This is a list of all of the internal xine video buffer types that ++ * this decoder is able to handle. Check src/xine-engine/buffer.h for a ++ * list of valid buffer types (and add a new one if the one you need does ++ * not exist). Terminate the list with a 0. ++ */ ++static const uint32_t video_types[] = { ++ BUF_VIDEO_VC1, BUF_VIDEO_WMV9, ++ 0 ++}; ++ ++/* ++ * This data structure combines the list of supported xine buffer types and ++ * the priority that the plugin should be given with respect to other ++ * plugins that handle the same buffer type. A plugin with priority (n+1) ++ * will be used instead of a plugin with priority (n). ++ */ ++static const decoder_info_t dec_info_video = { ++ video_types, /* supported types */ ++ 8 /* priority */ ++}; ++ ++/* ++ * The plugin catalog entry. This is the only information that this plugin ++ * will export to the public. ++ */ ++const plugin_info_t xine_plugin_info[] EXPORTED = { ++ /* { type, API, "name", version, special_info, init_function } */ ++ { PLUGIN_VIDEO_DECODER, 18, "vdpau_vc1", XINE_VERSION_CODE, &dec_info_video, init_plugin }, ++ { PLUGIN_NONE, 0, "", 0, NULL, NULL } ++}; +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/Makefile.am +@@ -0,0 +1,27 @@ ++include $(top_srcdir)/misc/Makefile.common ++ ++AM_CFLAGS = $(VISIBILITY_FLAG) ++AM_LDFLAGS = $(xineplug_ldflags) ++ ++if HAVE_VDPAU ++vdpau_h264_module = xineplug_decode_vdpau_h264.la ++VDPAU_CFLAGS = -D_ISOC99_SOURCE ++ ++vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la ++ ++vdpau_vc1_module = xineplug_decode_vdpau_vc1.la ++endif ++ ++xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) $(vdpau_vc1_module) ++ ++xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c ++xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) ++xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) -lm ++ ++xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c ++xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS) ++xineplug_decode_vdpau_mpeg12_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) ++ ++xineplug_decode_vdpau_vc1_la_SOURCES = vdpau_vc1.c ++xineplug_decode_vdpau_vc1_la_CFLAGS = $(AM_CFLAGS) ++xineplug_decode_vdpau_vc1_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/h264_parser.h +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (C) 2008 Julian Scheel ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * h264_parser.h: Almost full-features H264 NAL-Parser ++ */ ++ ++#ifndef NAL_PARSER_H_ ++#define NAL_PARSER_H_ ++ ++#include ++ ++#include "xine_internal.h" ++#include "nal.h" ++#include "dpb.h" ++ ++#define MAX_FRAME_SIZE 1024*1024 ++ ++struct nal_parser { ++ uint8_t buf[MAX_FRAME_SIZE]; ++ uint32_t buf_len; ++ ++ /* prebuf is used to store the currently ++ * processed nal unit */ ++ uint8_t prebuf[MAX_FRAME_SIZE]; ++ uint32_t prebuf_len; ++ uint32_t next_nal_position; ++ uint8_t incomplete_nal; ++ ++ uint8_t found_sps; ++ uint8_t found_pps; ++ uint8_t last_nal_res; ++ ++ uint8_t is_idr; ++ ++ int field; /* 0=top, 1=bottom, -1=both */ ++ int slice; ++ int slice_cnt; ++ ++ uint8_t have_top; ++ uint8_t have_frame; ++ ++ uint8_t nal_size_length; ++ uint32_t next_nal_size; ++ uint8_t *nal_size_length_buf; ++ uint8_t have_nal_size_length_buf; ++ ++ struct nal_unit *nal0; ++ struct nal_unit *nal1; ++ struct nal_unit *current_nal; ++ struct nal_unit *last_nal; ++ ++ uint8_t cpb_dpb_delays_present_flag; ++ ++ uint32_t pic_order_cnt_lsb; ++ uint32_t pic_order_cnt_msb; ++ uint32_t prev_pic_order_cnt_lsb; ++ uint32_t prev_pic_order_cnt_msb; ++ uint32_t frame_num_offset; ++ ++ /* this is dpb used for reference frame ++ * heading to vdpau + unordered frames ++ */ ++ struct dpb dpb; ++}; ++ ++int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); ++ ++int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); ++ ++struct nal_parser* init_parser(); ++void free_parser(struct nal_parser *parser); ++int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, ++ uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt); ++ ++/* this has to be called after decoding the frame delivered by parse_frame, ++ * but before adding a decoded frame to the dpb. ++ */ ++void process_mmc_operations(struct nal_parser *parser); ++ ++void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len); ++ ++#endif +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/bits_reader.h +@@ -0,0 +1,36 @@ ++#include ++ ++ ++ ++typedef struct { ++ uint8_t *buffer; ++ int offbits; ++} bits_reader_t; ++ ++static void bits_reader_set( bits_reader_t *br, uint8_t *buf ) ++{ ++ br->buffer = buf; ++ br->offbits = 0; ++} ++ ++static uint32_t read_bits( bits_reader_t *br, int nbits ) ++{ ++ int i, nbytes; ++ uint32_t ret = 0; ++ uint8_t *buf; ++ ++ buf = br->buffer; ++ nbytes = (br->offbits + nbits)/8; ++ if ( ((br->offbits + nbits) %8 ) > 0 ) ++ nbytes++; ++ for ( i=0; ioffbits; ++ ret = ((ret<>i)>>((nbytes*8)-nbits-br->offbits); ++ ++ br->offbits += nbits; ++ br->buffer += br->offbits / 8; ++ br->offbits %= 8; ++ ++ return ret; ++} +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/dpb.h +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (C) 2008 Julian Scheel ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * dpb.h: Decoder Picture Buffer ++ */ ++ ++#ifndef DPB_H_ ++#define DPB_H_ ++ ++#define MAX_DPB_SIZE 16 ++ ++#include "nal.h" ++#include "video_out.h" ++ ++struct decoded_picture { ++ VdpVideoSurface surface; ++ vo_frame_t *img; /* this is the image we block, to make sure ++ * the surface is not double-used */ ++ struct nal_unit *nal; ++ ++ uint8_t used_for_reference; ++ uint8_t top_is_reference; ++ uint8_t bottom_is_reference; ++ ++ uint8_t delayed_output; ++ ++ struct decoded_picture *next; ++}; ++ ++/* Decoded Picture Buffer */ ++struct dpb { ++ struct decoded_picture *pictures; ++ ++ uint32_t num_ref_frames; ++ uint32_t used; ++}; ++ ++struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, ++ VdpVideoSurface surface, vo_frame_t *img); ++void free_decoded_picture(struct decoded_picture *pic); ++ ++struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush); ++ ++struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum); ++struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); ++struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); ++ ++int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum); ++int dpb_set_unused_ref_picture_a(struct dpb *dpb, struct decoded_picture *refpic); ++int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum); ++int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx); ++int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx); ++ ++int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic); ++ ++int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic); ++int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames); ++int dpb_flush(struct dpb *dpb); ++void dpb_free_all( struct dpb *dpb ); ++void dpb_clear_all_pts( struct dpb *dpb ); ++ ++int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); ++ ++#endif /* DPB_H_ */ +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/nal.h +@@ -0,0 +1,466 @@ ++/* ++ * Copyright (C) 2008 Julian Scheel ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * nal.h: H264 NAL structures ++ */ ++ ++#ifndef NAL_H_ ++#define NAL_H_ ++#include ++#include ++ ++enum nal_unit_types ++{ ++ NAL_UNSPECIFIED = 0, ++ NAL_SLICE, ++ NAL_PART_A, ++ NAL_PART_B, ++ NAL_PART_C, ++ NAL_SLICE_IDR, ++ NAL_SEI, ++ NAL_SPS, ++ NAL_PPS, ++ NAL_AU_DELIMITER, ++ NAL_END_OF_SEQUENCE, ++ NAL_END_OF_STREAM, ++ NAL_FILLER_DATA, ++ NAL_SPS_EXT ++}; ++ ++enum pic_struct { ++ DISP_FRAME = 0, ++ DISP_TOP, ++ DISP_BOTTOM, ++ DISP_TOP_BOTTOM, ++ DISP_BOTTOM_TOP, ++ DISP_TOP_BOTTOM_TOP, ++ DISP_TOP_TOP_BOTTOM, ++ DISP_BOTTOM_TOP_BOTTOM, ++ DISP_FRAME_DOUBLING, ++ DISP_FRAME_TRIPLING ++}; ++ ++/* slice types repeat from 5-9, we ++ * need a helper function for comparison ++ */ ++enum slice_types ++{ ++ SLICE_P = 0, SLICE_B, SLICE_I, SLICE_SP, SLICE_SI ++}; ++ ++enum aspect_ratio ++{ ++ ASPECT_UNSPECIFIED = 0, ++ ASPECT_1_1, ++ ASPECT_12_11, ++ ASPECT_10_11, ++ ASPECT_16_11, ++ ASPECT_40_33, ++ ASPECT_24_11, ++ ASPECT_20_11, ++ ASPECT_32_11, ++ ASPECT_80_33, ++ ASPECT_18_11, ++ ASPECT_15_11, ++ ASPECT_64_33, ++ ASPECT_160_99, ++ ASPECT_4_3, ++ ASPECT_3_2, ++ ASPECT_2_1, ++ ASPECT_RESERVED, ++ ASPECT_EXTENDED_SAR=255 ++}; ++ ++static const uint8_t zigzag_4x4[16] = { ++ 0+0*4, 1+0*4, 0+1*4, 0+2*4, ++ 1+1*4, 2+0*4, 3+0*4, 2+1*4, ++ 1+2*4, 0+3*4, 1+3*4, 2+2*4, ++ 3+1*4, 3+2*4, 2+3*4, 3+3*4, ++}; ++ ++static const uint8_t zigzag_8x8[64] = { ++ 0+0*8, 1+0*8, 0+1*8, 0+2*8, ++ 1+1*8, 2+0*8, 3+0*8, 2+1*8, ++ 1+2*8, 0+3*8, 0+4*8, 1+3*8, ++ 2+2*8, 3+1*8, 4+0*8, 5+0*8, ++ 4+1*8, 3+2*8, 2+3*8, 1+4*8, ++ 0+5*8, 0+6*8, 1+5*8, 2+4*8, ++ 3+3*8, 4+2*8, 5+1*8, 6+0*8, ++ 7+0*8, 6+1*8, 5+2*8, 4+3*8, ++ 3+4*8, 2+5*8, 1+6*8, 0+7*8, ++ 1+7*8, 2+6*8, 3+5*8, 4+4*8, ++ 5+3*8, 6+2*8, 7+1*8, 7+2*8, ++ 6+3*8, 5+4*8, 4+5*8, 3+6*8, ++ 2+7*8, 3+7*8, 4+6*8, 5+5*8, ++ 6+4*8, 7+3*8, 7+4*8, 6+5*8, ++ 5+6*8, 4+7*8, 5+7*8, 6+6*8, ++ 7+5*8, 7+6*8, 6+7*8, 7+7*8, ++}; ++ ++static inline uint32_t slice_type(uint32_t slice_type) ++{ ++ return (slice_type < 10 ? slice_type % 5 : slice_type); ++} ++ ++static inline void print_slice_type(uint32_t slice_type) ++{ ++ switch(slice_type) { ++ case SLICE_P: ++ printf("SLICE_P\n"); ++ break; ++ case SLICE_B: ++ printf("SLICE_B\n"); ++ break; ++ case SLICE_I: ++ printf("SLICE_I\n"); ++ break; ++ case SLICE_SP: ++ printf("SLICE_SP\n"); ++ break; ++ case SLICE_SI: ++ printf("SLICE_SI\n"); ++ break; ++ default: ++ printf("Unknown SLICE\n"); ++ } ++} ++ ++struct hrd_parameters ++{ ++ uint32_t cpb_cnt_minus1; ++ uint8_t bit_rate_scale; ++ uint8_t cpb_size_scale; ++ ++ uint32_t bit_rate_value_minus1[32]; ++ uint32_t cpb_size_value_minus1[32]; ++ uint8_t cbr_flag[32]; ++ ++ uint8_t initial_cpb_removal_delay_length_minus1; ++ uint8_t cpb_removal_delay_length_minus1; ++ uint8_t dpb_output_delay_length_minus1; ++ uint8_t time_offset_length; ++}; ++ ++struct seq_parameter_set_rbsp ++{ ++ uint8_t profile_idc; // 0xff ++ uint8_t constraint_setN_flag; // 0x0f ++ uint8_t level_idc; // 0xff ++ uint32_t seq_parameter_set_id; ++ uint32_t chroma_format_idc; ++ uint8_t separate_colour_plane_flag; // 0x01 ++ uint32_t bit_depth_luma_minus8; ++ uint32_t bit_depth_chroma_minus8; ++ uint8_t qpprime_y_zero_transform_bypass_flag; ++ uint8_t seq_scaling_matrix_present_flag; ++ ++ /* if(seq_scaling_matrix_present_flag) */ ++ uint8_t seq_scaling_list_present_flag[8]; ++ ++ uint8_t scaling_lists_4x4[6][16]; ++ uint8_t scaling_lists_8x8[2][64]; ++ /* endif */ ++ ++ uint32_t log2_max_frame_num_minus4; ++ uint32_t pic_order_cnt_type; ++ // if pic_order_cnt_type==0 ++ uint32_t log2_max_pic_order_cnt_lsb_minus4; ++ // else ++ uint8_t delta_pic_order_always_zero_flag; ++ int32_t offset_for_non_ref_pic; ++ int32_t offset_for_top_to_bottom_field; ++ uint8_t num_ref_frames_in_pic_order_cnt_cycle; ++ int32_t offset_for_ref_frame[256]; ++ // TODO: some more ignored here ++ uint32_t num_ref_frames; ++ uint8_t gaps_in_frame_num_value_allowed_flag; ++ /*uint32_t pic_width_in_mbs_minus1; ++ uint32_t pic_height_in_map_units_minus1;*/ ++ uint32_t pic_width; ++ uint32_t pic_height; ++ uint8_t frame_mbs_only_flag; ++ uint8_t mb_adaptive_frame_field_flag; ++ uint8_t direct_8x8_inference_flag; ++ uint8_t frame_cropping_flag; ++ uint32_t frame_crop_left_offset; ++ uint32_t frame_crop_right_offset; ++ uint32_t frame_crop_top_offset; ++ uint32_t frame_crop_bottom_offset; ++ uint8_t vui_parameters_present_flag; ++ ++ /* vui_parameters */ ++ struct ++ { ++ uint8_t aspect_ration_info_present_flag; ++ ++ /* aspect_ration_info_present_flag == 1 */ ++ uint8_t aspect_ratio_idc; ++ uint16_t sar_width; ++ uint16_t sar_height; ++ ++ uint8_t overscan_info_present_flag; ++ /* overscan_info_present_flag == 1 */ ++ uint8_t overscan_appropriate_flag; ++ ++ uint8_t video_signal_type_present_flag; ++ /* video_signal_type_present_flag == 1 */ ++ uint8_t video_format; ++ uint8_t video_full_range_flag; ++ uint8_t colour_description_present; ++ /* colour_description_present == 1 */ ++ uint8_t colour_primaries; ++ uint8_t transfer_characteristics; ++ uint8_t matrix_coefficients; ++ ++ uint8_t chroma_loc_info_present_flag; ++ /* chroma_loc_info_present_flag == 1 */ ++ uint8_t chroma_sample_loc_type_top_field; ++ uint8_t chroma_sample_loc_type_bottom_field; ++ ++ uint8_t timing_info_present_flag; ++ /* timing_info_present_flag == 1 */ ++ uint32_t num_units_in_tick; ++ uint32_t time_scale; ++ uint8_t fixed_frame_rate_flag; ++ ++ uint8_t nal_hrd_parameters_present_flag; ++ struct hrd_parameters nal_hrd_parameters; ++ ++ uint8_t vc1_hrd_parameters_present_flag; ++ struct hrd_parameters vc1_hrd_parameters; ++ ++ uint8_t low_delay_hrd_flag; ++ ++ uint8_t pic_struct_present_flag; ++ uint8_t bitstream_restriction_flag; ++ ++ /* bitstream_restriction_flag == 1 */ ++ uint8_t motion_vectors_over_pic_boundaries; ++ uint32_t max_bytes_per_pic_denom; ++ uint32_t max_bits_per_mb_denom; ++ uint32_t log2_max_mv_length_horizontal; ++ uint32_t log2_max_mv_length_vertical; ++ uint32_t num_reorder_frames; ++ uint32_t max_dec_frame_buffering; ++ } vui_parameters; ++ ++}; ++ ++struct pic_parameter_set_rbsp ++{ ++ uint32_t pic_parameter_set_id; ++ uint32_t seq_parameter_set_id; ++ uint8_t entropy_coding_mode_flag; ++ uint8_t pic_order_present_flag; ++ ++ uint32_t num_slice_groups_minus1; ++ ++ /* num_slice_groups_minus1 > 0 */ ++ uint32_t slice_group_map_type; ++ ++ /* slice_group_map_type == 1 */ ++ uint32_t run_length_minus1[64]; ++ ++ /* slice_group_map_type == 2 */ ++ uint32_t top_left[64]; ++ uint32_t bottom_right[64]; ++ ++ /* slice_group_map_type == 3,4,5 */ ++ uint8_t slice_group_change_direction_flag; ++ uint32_t slice_group_change_rate_minus1; ++ ++ /* slice_group_map_type == 6 */ ++ uint32_t pic_size_in_map_units_minus1; ++ uint8_t slice_group_id[64]; ++ ++ uint32_t num_ref_idx_l0_active_minus1; ++ uint32_t num_ref_idx_l1_active_minus1; ++ uint8_t weighted_pred_flag; ++ uint8_t weighted_bipred_idc; ++ int32_t pic_init_qp_minus26; ++ int32_t pic_init_qs_minus26; ++ int32_t chroma_qp_index_offset; ++ uint8_t deblocking_filter_control_present_flag; ++ uint8_t constrained_intra_pred_flag; ++ uint8_t redundant_pic_cnt_present_flag; ++ ++ /* if(more_rbsp_data) */ ++ uint8_t transform_8x8_mode_flag; ++ uint8_t pic_scaling_matrix_present_flag; ++ ++ /* if(pic_scaling_matrix_present_flag) */ ++ uint8_t pic_scaling_list_present_flag[8]; ++ ++ uint8_t scaling_lists_4x4[6][16]; ++ uint8_t scaling_lists_8x8[2][64]; ++ ++ int32_t second_chroma_qp_index_offset; ++}; ++ ++/*struct clock_timestamp { ++ uint8_t ct_type; ++ uint8_t nuit_fiel_based_flag; ++ uint8_t counting_type; ++ uint8_t full_timestamp_flag; ++ uint8_t discontinuity_flag; ++ uint8_t cnt_dropped_flag; ++ uint8_t n_frames ++};*/ ++ ++/* sei contains several additional info, we do ++ * only care for pic_timing, to handle display ++ * reordering ++ */ ++struct sei_message ++{ ++ uint32_t payload_type; ++ uint8_t last_payload_type_byte; ++ uint32_t payload_size; ++ uint8_t last_payload_size_byte; ++ ++ struct ++ { ++ /* cpb_dpb_delays_present_flag == 1 */ ++ uint8_t cpb_removal_delay; ++ uint8_t dpb_output_delay; ++ ++ uint8_t pic_struct; ++ //uint8_t clock_timestamp_flag[3]; ++ } pic_timing; ++}; ++ ++struct slice_header ++{ ++ uint32_t first_mb_in_slice; ++ uint32_t slice_type; ++ uint32_t pic_parameter_set_id; ++ uint8_t colour_plane_id; ++ uint32_t frame_num; ++ uint8_t field_pic_flag; ++ uint8_t bottom_field_flag; ++ uint32_t idr_pic_id; ++ ++ /* sps->pic_order_cnt_type == 0 */ ++ uint32_t pic_order_cnt_lsb; ++ int32_t delta_pic_order_cnt_bottom; ++ /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ ++ int32_t delta_pic_order_cnt[2]; ++ ++ /* pps->redundant_pic_cnt_present_flag == 1 */ ++ int32_t redundant_pic_cnt; ++ ++ /* slice_type == B */ ++ uint8_t direct_spatial_mv_pred_flag; ++ ++ /* slice_type == P, SP, B */ ++ uint8_t num_ref_idx_active_override_flag; ++ /* num_ref_idx_active_override_flag == 1 */ ++ uint32_t num_ref_idx_l0_active_minus1; ++ /* slice type == B */ ++ uint32_t num_ref_idx_l1_active_minus1; ++ ++ /* ref_pic_list_reordering */ ++ struct ++ { ++ /* slice_type != I && slice_type != SI */ ++ uint8_t ref_pic_list_reordering_flag_l0; ++ ++ /* slice_type == B */ ++ uint8_t ref_pic_list_reordering_flag_l1; ++ ++ /* ref_pic_list_reordering_flag_l0 == 1 */ ++ uint32_t reordering_of_pic_nums_idc; ++ ++ /* reordering_of_pic_nums_idc == 0, 1 */ ++ uint32_t abs_diff_pic_num_minus1; ++ ++ /* reordering_of_pic_nums_idc == 2) */ ++ uint32_t long_term_pic_num; ++ } ref_pic_list_reordering; ++ ++ /* pred_weight_table */ ++ struct ++ { ++ uint32_t luma_log2_weight_denom; ++ ++ /* chroma_format_idc != 0 */ ++ uint32_t chroma_log2_weight_denom; ++ ++ int32_t luma_weight_l0[32]; ++ int32_t luma_offset_l0[32]; ++ ++ int32_t chroma_weight_l0[32][2]; ++ int32_t chroma_offset_l0[32][2]; ++ ++ int32_t luma_weight_l1[32]; ++ int32_t luma_offset_l1[32]; ++ ++ int32_t chroma_weight_l1[32][2]; ++ int32_t chroma_offset_l1[32][2]; ++ } pred_weight_table; ++ ++ /* def_rec_pic_marking */ ++ struct ++ { ++ ++ /* nal_unit_type == NAL_SLICE_IDR */ ++ uint8_t no_output_of_prior_pics_flag; ++ uint8_t long_term_reference_flag; ++ ++ /* else */ ++ uint8_t adaptive_ref_pic_marking_mode_flag; ++ uint32_t memory_management_control_operation; ++ ++ uint32_t difference_of_pic_nums_minus1; ++ uint32_t long_term_pic_num; ++ uint32_t long_term_frame_idx; ++ uint32_t max_long_term_frame_idx_plus1; ++ } dec_ref_pic_marking[10]; ++ uint32_t dec_ref_pic_marking_count; ++}; ++ ++struct nal_unit ++{ ++ uint8_t nal_ref_idc; // 0x03 ++ uint8_t nal_unit_type; // 0x1f ++ ++ uint32_t max_pic_num; ++ uint32_t curr_pic_num; ++ uint8_t used_for_long_term_ref; ++ uint32_t long_term_pic_num; ++ uint32_t long_term_frame_idx; ++ ++ int32_t top_field_order_cnt; ++ int32_t bottom_field_order_cnt; ++ ++ uint8_t interlaced; ++ uint8_t repeat_pic; ++ ++ struct sei_message sei; ++ ++ struct seq_parameter_set_rbsp *sps; ++ struct pic_parameter_set_rbsp *pps; ++ struct slice_header *slc; ++}; ++ ++struct nal_unit* init_nal_unit(); ++void free_nal_unit(struct nal_unit *nal); ++void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src); ++ ++#endif /* NAL_H_ */ +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/h264_parser.c +@@ -0,0 +1,1594 @@ ++/* ++ * Copyright (C) 2008 Julian Scheel ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * h264_parser.c: Almost full-features H264 NAL-Parser ++ */ ++ ++#include ++#include ++#include ++ ++#include "h264_parser.h" ++#include "nal.h" ++ ++/* default scaling_lists according to Table 7-2 */ ++uint8_t default_4x4_intra[16] = { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, ++ 32, 32, 37, 37, 42 }; ++ ++uint8_t default_4x4_inter[16] = { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, ++ 27, 27, 30, 30, 34 }; ++ ++uint8_t default_8x8_intra[64] = { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, ++ 18, 18, 18, 18, 23, 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, ++ 27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, ++ 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; ++ ++uint8_t default_8x8_inter[64] = { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, ++ 19, 19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, ++ 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, ++ 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; ++ ++struct buf_reader ++{ ++ uint8_t *buf; ++ uint8_t *cur_pos; ++ int len; ++ int cur_offset; ++}; ++ ++static inline uint32_t read_bits(struct buf_reader *buf, int len); ++uint32_t read_exp_golomb(struct buf_reader *buf); ++int32_t read_exp_golomb_s(struct buf_reader *buf); ++ ++void calculate_pic_order(struct nal_parser *parser); ++void skip_scaling_list(struct buf_reader *buf, int size); ++void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, ++ int length, int index); ++int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser); ++static void sps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, int i); ++static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct pic_parameter_set_rbsp *pps, int i); ++uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser); ++void parse_vui_parameters(struct buf_reader *buf, ++ struct seq_parameter_set_rbsp *sps); ++void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); ++uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, ++ struct seq_parameter_set_rbsp *sps); ++void parse_sei(struct buf_reader *buf, struct nal_parser *parser); ++uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); ++void ++ parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, ++ struct nal_parser *parser); ++void decode_ref_pic_marking(struct nal_unit *nal, ++ uint32_t memory_management_control_operation, ++ uint32_t marking_nr, ++ struct nal_parser *parser); ++void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); ++void parse_dec_ref_pic_marking(struct buf_reader *buf, ++ struct nal_parser *parser); ++ ++/* here goes the parser implementation */ ++ ++static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) ++{ ++ uint8_t *end = &buf[buf_len]; ++ uint8_t *pos = malloc(buf_len); ++ ++ *ret = pos; ++ while (buf < end) { ++ if (buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x03) { ++ ++ *pos++ = 0x00; ++ *pos++ = 0x00; ++ ++ buf += 3; ++ continue; ++ } ++ *pos++ = *buf++; ++ } ++ ++ *len_ret = pos - *ret; ++} ++ ++#if 0 ++static inline void dump_bits(const char *label, const struct buf_reader *buf, int bits) ++{ ++ struct buf_reader lbuf; ++ memcpy(&lbuf, buf, sizeof(struct buf_reader)); ++ ++ int i; ++ printf("%s: 0b", label); ++ for(i=0; i < bits; i++) ++ printf("%d", read_bits(&lbuf, 1)); ++ printf("\n"); ++} ++#endif ++ ++static inline uint32_t bits_read(struct buf_reader *buf) ++{ ++ int bits_read = 0; ++ bits_read = (buf->cur_pos - buf->buf)*8; ++ bits_read += (8-buf->cur_offset); ++ ++ return bits_read; ++} ++ ++static inline uint32_t read_bits(struct buf_reader *buf, int len) ++{ ++ static uint32_t i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, ++ 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, ++ 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, ++ 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, ++ 0x3fffffff, 0x7fffffff, 0xffffffff }; ++ ++ int i_shr; ++ uint32_t bits = 0; ++ ++ while (len > 0 && (buf->cur_pos - buf->buf) < buf->len) { ++ if ((i_shr = buf->cur_offset - len) >= 0) { ++ bits |= (*buf->cur_pos >> i_shr) & i_mask[len]; ++ buf->cur_offset -= len; ++ if (buf->cur_offset == 0) { ++ buf->cur_pos++; ++ buf->cur_offset = 8; ++ } ++ return bits; ++ } ++ else { ++ bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; ++ len -= buf->cur_offset; ++ buf->cur_pos++; ++ buf->cur_offset = 8; ++ } ++ } ++ return bits; ++} ++ ++/* determines if following bits are rtsb_trailing_bits */ ++static inline int rbsp_trailing_bits(uint8_t *buf, int buf_len) ++{ ++ uint8_t *cur_buf = buf+(buf_len-1); ++ uint8_t cur_val; ++ int parsed_bits = 0; ++ int i; ++ ++ while(buf_len > 0) { ++ cur_val = *cur_buf; ++ for(i = 0; i < 9; i++) { ++ if (cur_val&1) ++ return parsed_bits+i; ++ cur_val>>=1; ++ } ++ parsed_bits += 8; ++ cur_buf--; ++ } ++ ++ printf("rbsp trailing bits could not be found\n"); ++ return 0; ++} ++ ++uint32_t read_exp_golomb(struct buf_reader *buf) ++{ ++ int leading_zero_bits = 0; ++ ++ while (read_bits(buf, 1) == 0 && leading_zero_bits < 32) ++ leading_zero_bits++; ++ ++ uint32_t code = (1 << leading_zero_bits) - 1 + read_bits(buf, ++ leading_zero_bits); ++ return code; ++} ++ ++int32_t read_exp_golomb_s(struct buf_reader *buf) ++{ ++ uint32_t ue = read_exp_golomb(buf); ++ int32_t code = ue & 0x01 ? (ue + 1) / 2 : -(ue / 2); ++ return code; ++} ++ ++int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) ++{ ++ if (buf->len < 1) ++ return -1; ++ ++ int ret = -1; ++ ++ struct nal_unit *nal = parser->current_nal; ++ ++ memset(nal, 0x00, sizeof(struct nal_unit) - sizeof(struct seq_parameter_set_rbsp*) - sizeof(struct pic_parameter_set_rbsp*) - sizeof(struct slice_header*)); ++ nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; ++ nal->nal_unit_type = buf->buf[0] & 0x1f; ++ ++ buf->cur_pos = buf->buf + 1; ++ //printf("NAL: %d\n", nal->nal_unit_type); ++ ++ struct buf_reader ibuf; ++ ibuf.cur_offset = 8; ++ ++ switch (nal->nal_unit_type) { ++ case NAL_SPS: ++ decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len - 1); ++ ibuf.cur_pos = ibuf.buf; ++ ++ if (!nal->sps) ++ nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); ++ else ++ memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); ++ ++ parse_sps(&ibuf, parser); ++ free(ibuf.buf); ++ ret = NAL_SPS; ++ break; ++ case NAL_PPS: ++ if (!nal->pps) ++ nal->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); ++ else ++ memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); ++ ++ parse_pps(buf, nal->pps, nal->sps); ++ ret = NAL_PPS; ++ break; ++ case NAL_SLICE: ++ case NAL_PART_A: ++ case NAL_PART_B: ++ case NAL_PART_C: ++ case NAL_SLICE_IDR: ++ if (nal->sps && nal->pps) { ++ if (!nal->slc) ++ nal->slc = calloc(1, sizeof(struct slice_header)); ++ else ++ memset(nal->slc, 0x00, sizeof(struct slice_header)); ++ ++ parse_slice_header(buf, parser); ++ ret = nal->nal_unit_type; ++ } ++ break; ++ case NAL_SEI: ++ memset(&(nal->sei), 0x00, sizeof(struct sei_message)); ++ parse_sei(buf, parser); ++ ret = nal->nal_unit_type; ++ break; ++ default: ++ ret = nal->nal_unit_type; ++ break; ++ } ++ ++ return ret; ++} ++ ++void calculate_pic_order(struct nal_parser *parser) ++{ ++ struct nal_unit *nal = parser->current_nal; ++ ++ struct seq_parameter_set_rbsp *sps = nal->sps; ++ struct slice_header *slc = nal->slc; ++ if (!sps || !slc) ++ return; ++ ++ if (nal->nal_unit_type == NAL_SLICE_IDR) { ++ parser->prev_pic_order_cnt_lsb = 0; ++ parser->prev_pic_order_cnt_msb = 0; ++ parser->frame_num_offset = 0; ++ } ++ ++ if (sps->pic_order_cnt_type == 0) { ++ ++ const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); ++ ++ if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb ++ && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb ++ >= max_poc_lsb / 2) ++ parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + max_poc_lsb; ++ else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb ++ && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb ++ < -max_poc_lsb / 2) ++ parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - max_poc_lsb; ++ else ++ parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; ++ ++ if(!slc->field_pic_flag || !slc->bottom_field_flag) ++ nal->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; ++ ++ nal->bottom_field_order_cnt = 0; ++ ++ if(!slc->field_pic_flag) ++ nal->bottom_field_order_cnt = nal->top_field_order_cnt + slc->delta_pic_order_cnt_bottom; ++ else //if(slc->bottom_field_flag) TODO: this is not spec compliant, but works... ++ nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; ++ ++ /*if(slc->bottom_field_flag) ++ nal->top_field_order_cnt = parser->last_nal->top_field_order_cnt;*/ ++ ++ } else if (sps->pic_order_cnt_type == 2) { ++ uint32_t prev_frame_num = parser->last_nal->slc->frame_num; ++ uint32_t prev_frame_num_offset = parser->frame_num_offset; ++ uint32_t max_frame_num = 1 << (sps->log2_max_frame_num_minus4+4); ++ uint32_t temp_pic_order_cnt = 0; ++ ++ if (parser->is_idr) ++ parser->frame_num_offset = 0; ++ else if (prev_frame_num > slc->frame_num) ++ parser->frame_num_offset = prev_frame_num_offset + max_frame_num; ++ else ++ parser->frame_num_offset = prev_frame_num_offset; ++ ++ if(parser->is_idr) ++ temp_pic_order_cnt = 0; ++ else if(nal->nal_ref_idc == 0) ++ temp_pic_order_cnt = 2 * (parser->frame_num_offset + slc->frame_num)-1; ++ else ++ temp_pic_order_cnt = 2 * (parser->frame_num_offset + slc->frame_num); ++ ++ if(!slc->field_pic_flag) ++ nal->top_field_order_cnt = nal->bottom_field_order_cnt = temp_pic_order_cnt; ++ else if(slc->bottom_field_flag) ++ nal->bottom_field_order_cnt = temp_pic_order_cnt; ++ else ++ nal->top_field_order_cnt = temp_pic_order_cnt; ++ ++ } else { ++ printf("FIXME: Unsupported poc_type: %d\n", sps->pic_order_cnt_type); ++ } ++ ++} ++ ++void skip_scaling_list(struct buf_reader *buf, int size) ++{ ++ int i; ++ for (i = 0; i < size; i++) { ++ read_exp_golomb_s(buf); ++ } ++} ++ ++void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, ++ int length, int index) ++{ ++ int last_scale = 8; ++ int next_scale = 8; ++ int32_t delta_scale; ++ uint8_t use_default_scaling_matrix_flag = 0; ++ int i; ++ ++ uint8_t *zigzag = (length==64) ? zigzag_8x8 : zigzag_4x4; ++ ++ for (i = 0; i < length; i++) { ++ if (next_scale != 0) { ++ delta_scale = read_exp_golomb_s(buf); ++ next_scale = (last_scale + delta_scale + 256) % 256; ++ if (i == 0 && next_scale == 0) { ++ use_default_scaling_matrix_flag = 1; ++ break; ++ } ++ } ++ scaling_list[zigzag[i]] = last_scale = (next_scale == 0) ? last_scale : next_scale; ++ } ++ ++ if (use_default_scaling_matrix_flag) { ++ switch (index) { ++ case 0: ++ case 1: ++ case 2: { ++ for(i = 0; i < sizeof(default_4x4_intra); i++) { ++ scaling_list[zigzag_4x4[i]] = default_4x4_intra[i]; ++ } ++ //memcpy(scaling_list, default_4x4_intra, sizeof(default_4x4_intra)); ++ break; ++ } ++ case 3: ++ case 4: ++ case 5: { ++ for(i = 0; i < sizeof(default_4x4_inter); i++) { ++ scaling_list[zigzag_4x4[i]] = default_4x4_inter[i]; ++ } ++ //memcpy(scaling_list, default_4x4_inter, sizeof(default_4x4_inter)); ++ break; ++ } ++ case 6: { ++ for(i = 0; i < sizeof(default_8x8_intra); i++) { ++ scaling_list[zigzag_8x8[i]] = default_8x8_intra[i]; ++ } ++ //memcpy(scaling_list, default_8x8_intra, sizeof(default_8x8_intra)); ++ break; ++ } ++ case 7: { ++ for(i = 0; i < sizeof(default_8x8_inter); i++) { ++ scaling_list[zigzag_8x8[i]] = default_8x8_inter[i]; ++ } ++ //memcpy(scaling_list, default_8x8_inter, sizeof(default_8x8_inter)); ++ break; ++ } ++ } ++ } ++} ++ ++static void sps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, int i) ++{ ++ int j; ++ switch (i) { ++ case 0: { ++ for(j = 0; j < sizeof(default_4x4_intra); j++) { ++ sps->scaling_lists_4x4[i][zigzag_4x4[j]] = default_4x4_intra[j]; ++ } ++ //memcpy(sps->scaling_lists_4x4[i], default_4x4_intra, sizeof(sps->scaling_lists_4x4[i])); ++ break; ++ } ++ case 3: { ++ for(j = 0; j < sizeof(default_4x4_inter); j++) { ++ sps->scaling_lists_4x4[i][zigzag_4x4[j]] = default_4x4_inter[j]; ++ } ++ //memcpy(sps->scaling_lists_4x4[i], default_4x4_inter, sizeof(sps->scaling_lists_4x4[i])); ++ break; ++ } ++ case 1: ++ case 2: ++ case 4: ++ case 5: ++ memcpy(sps->scaling_lists_4x4[i], sps->scaling_lists_4x4[i-1], sizeof(sps->scaling_lists_4x4[i])); ++ break; ++ case 6: { ++ for(j = 0; j < sizeof(default_8x8_intra); j++) { ++ sps->scaling_lists_8x8[i-6][zigzag_8x8[j]] = default_8x8_intra[j]; ++ } ++ //memcpy(sps->scaling_lists_8x8[i-6], default_8x8_intra, sizeof(sps->scaling_lists_8x8[i-6])); ++ break; ++ } ++ case 7: { ++ for(j = 0; j < sizeof(default_8x8_inter); j++) { ++ sps->scaling_lists_8x8[i-6][zigzag_8x8[j]] = default_8x8_inter[j]; ++ } ++ //memcpy(sps->scaling_lists_8x8[i-6], default_8x8_inter, sizeof(sps->scaling_lists_8x8[i-6])); ++ break; ++ } ++ ++ } ++} ++ ++static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct pic_parameter_set_rbsp *pps, int i) ++{ ++ switch (i) { ++ case 0: ++ case 3: ++ memcpy(pps->scaling_lists_4x4[i], sps->scaling_lists_4x4[i], sizeof(pps->scaling_lists_4x4[i])); ++ break; ++ case 1: ++ case 2: ++ case 4: ++ case 5: ++ memcpy(pps->scaling_lists_4x4[i], pps->scaling_lists_4x4[i-1], sizeof(pps->scaling_lists_4x4[i])); ++ break; ++ case 6: ++ case 7: ++ memcpy(pps->scaling_lists_8x8[i-6], sps->scaling_lists_8x8[i-6], sizeof(pps->scaling_lists_8x8[i-6])); ++ break; ++ ++ } ++} ++ ++ ++uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) ++{ ++ struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; ++ sps->profile_idc = read_bits(buf, 8); ++ sps->constraint_setN_flag = read_bits(buf, 4); ++ read_bits(buf, 4); ++ sps->level_idc = read_bits(buf, 8); ++ ++ sps->seq_parameter_set_id = read_exp_golomb(buf); ++ ++ memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); ++ memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_8x8)); ++ if (sps->profile_idc == 100 || sps->profile_idc == 110 || sps->profile_idc ++ == 122 || sps->profile_idc == 244 || sps->profile_idc == 44 || ++ sps->profile_idc == 83 || sps->profile_idc == 86) { ++ sps->chroma_format_idc = read_exp_golomb(buf); ++ if (sps->chroma_format_idc == 3) { ++ sps->separate_colour_plane_flag = read_bits(buf, 1); ++ } ++ ++ sps->bit_depth_luma_minus8 = read_exp_golomb(buf); ++ sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); ++ sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); ++ sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); ++ if (sps->seq_scaling_matrix_present_flag) { ++ int i; ++ for (i = 0; i < 8; i++) { ++ sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); ++ ++ if (sps->seq_scaling_list_present_flag[i]) { ++ if (i < 6) ++ parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); ++ else ++ parse_scaling_list(buf, sps->scaling_lists_8x8[i - 6], 64, i); ++ } else { ++ sps_scaling_list_fallback(sps, i); ++ } ++ } ++ } ++ } else ++ sps->chroma_format_idc = 1; ++ ++ sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); ++ ++ sps->pic_order_cnt_type = read_exp_golomb(buf); ++ if (!sps->pic_order_cnt_type) ++ sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); ++ else if(sps->pic_order_cnt_type == 1) { ++ sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); ++ sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); ++ sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); ++ sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); ++ int i; ++ for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) { ++ sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); ++ } ++ } ++ ++ sps->num_ref_frames = read_exp_golomb(buf); ++ sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); ++ ++ /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); ++ sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ ++ sps->pic_width = 16 * (read_exp_golomb(buf) + 1); ++ sps->pic_height = 16 * (read_exp_golomb(buf) + 1); ++ ++ sps->frame_mbs_only_flag = read_bits(buf, 1); ++ ++ /* compute the height correctly even for interlaced material */ ++ sps->pic_height = (2 - sps->frame_mbs_only_flag) * sps->pic_height; ++ if (sps->pic_height == 1088) ++ sps->pic_height = 1080; ++ ++ if (!sps->frame_mbs_only_flag) ++ sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); ++ ++ sps->direct_8x8_inference_flag = read_bits(buf, 1); ++ sps->frame_cropping_flag = read_bits(buf, 1); ++ if (sps->frame_cropping_flag) { ++ sps->frame_crop_left_offset = read_exp_golomb(buf); ++ sps->frame_crop_right_offset = read_exp_golomb(buf); ++ sps->frame_crop_top_offset = read_exp_golomb(buf); ++ sps->frame_crop_bottom_offset = read_exp_golomb(buf); ++ } ++ sps->vui_parameters_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters_present_flag) { ++ parse_vui_parameters(buf, sps); ++ if(sps->vui_parameters.nal_hrd_parameters_present_flag || ++ sps->vui_parameters.vc1_hrd_parameters_present_flag) { ++ parser->cpb_dpb_delays_present_flag = 1; ++ } else ++ parser->cpb_dpb_delays_present_flag = 0; ++ } else ++ parser->cpb_dpb_delays_present_flag = 0; ++ ++ return 0; ++} ++ ++void parse_sei(struct buf_reader *buf, struct nal_parser *parser) ++{ ++ struct sei_message *sei = &(parser->current_nal->sei); ++ struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; ++ uint8_t tmp; ++ ++ sei->payload_type = 0; ++ while((tmp = read_bits(buf, 8)) == 0xff) { ++ sei->payload_type += 255; ++ } ++ sei->last_payload_type_byte = tmp; ++ sei->payload_type += sei->last_payload_type_byte; ++ ++ sei->payload_size = 0; ++ while((tmp = read_bits(buf, 8)) == 0xff) { ++ sei->payload_size += 255; ++ } ++ sei->last_payload_size_byte = tmp; ++ sei->payload_size += sei->last_payload_size_byte; ++ ++ /* pic_timing */ ++ if(sei->payload_type == 1) { ++ if(parser->cpb_dpb_delays_present_flag) { ++ sei->pic_timing.cpb_removal_delay = read_bits(buf, 5); ++ sei->pic_timing.dpb_output_delay = read_bits(buf, 5); ++ } ++ ++ if(sps && sps->vui_parameters_present_flag && ++ sps->vui_parameters.pic_struct_present_flag) { ++ sei->pic_timing.pic_struct = read_bits(buf, 4); ++ switch(sei->pic_timing.pic_struct) { ++ case DISP_FRAME: ++ parser->current_nal->interlaced = 0; ++ parser->current_nal->repeat_pic = 0; ++ break; ++ case DISP_TOP: ++ case DISP_BOTTOM: ++ case DISP_TOP_BOTTOM: ++ case DISP_BOTTOM_TOP: ++ parser->current_nal->interlaced = 1; ++ break; ++ case DISP_TOP_BOTTOM_TOP: ++ case DISP_BOTTOM_TOP_BOTTOM: ++ parser->current_nal->interlaced = 1; ++ parser->current_nal->repeat_pic = 1; ++ break; ++ case DISP_FRAME_DOUBLING: ++ parser->current_nal->interlaced = 0; ++ parser->current_nal->repeat_pic = 2; ++ break; ++ case DISP_FRAME_TRIPLING: ++ parser->current_nal->interlaced = 0; ++ parser->current_nal->repeat_pic = 3; ++ } ++ } ++ } ++} ++ ++void parse_vui_parameters(struct buf_reader *buf, ++ struct seq_parameter_set_rbsp *sps) ++{ ++ sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters.aspect_ration_info_present_flag == 1) { ++ sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); ++ if (sps->vui_parameters.aspect_ratio_idc == ASPECT_EXTENDED_SAR) { ++ sps->vui_parameters.sar_width = read_bits(buf, 16); ++ sps->vui_parameters.sar_height = read_bits(buf, 16); ++ } ++ } ++ ++ sps->vui_parameters.overscan_info_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters.overscan_info_present_flag) { ++ sps->vui_parameters.overscan_appropriate_flag = read_bits(buf, 1); ++ } ++ ++ sps->vui_parameters.video_signal_type_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters.video_signal_type_present_flag) { ++ sps->vui_parameters.video_format = read_bits(buf, 3); ++ sps->vui_parameters.video_full_range_flag = read_bits(buf, 1); ++ sps->vui_parameters.colour_description_present = read_bits(buf, 1); ++ if (sps->vui_parameters.colour_description_present) { ++ sps->vui_parameters.colour_primaries = read_bits(buf, 8); ++ sps->vui_parameters.transfer_characteristics = read_bits(buf, 8); ++ sps->vui_parameters.matrix_coefficients = read_bits(buf, 8); ++ } ++ } ++ ++ sps->vui_parameters.chroma_loc_info_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters.chroma_loc_info_present_flag) { ++ sps->vui_parameters.chroma_sample_loc_type_top_field = read_exp_golomb(buf); ++ sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb( ++ buf); ++ } ++ ++ sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters.timing_info_present_flag) { ++ uint32_t num_units_in_tick = read_bits(buf, 32); ++ uint32_t time_scale = read_bits(buf, 32); ++ sps->vui_parameters.num_units_in_tick = num_units_in_tick; ++ sps->vui_parameters.time_scale = time_scale; ++ sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); ++ } ++ ++ sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters.nal_hrd_parameters_present_flag) ++ parse_hrd_parameters(buf, &sps->vui_parameters.nal_hrd_parameters); ++ ++ sps->vui_parameters.vc1_hrd_parameters_present_flag = read_bits(buf, 1); ++ if (sps->vui_parameters.vc1_hrd_parameters_present_flag) ++ parse_hrd_parameters(buf, &sps->vui_parameters.vc1_hrd_parameters); ++ ++ if (sps->vui_parameters.nal_hrd_parameters_present_flag ++ || sps->vui_parameters.vc1_hrd_parameters_present_flag) ++ sps->vui_parameters.low_delay_hrd_flag = read_bits(buf, 1); ++ ++ sps->vui_parameters.pic_struct_present_flag = read_bits(buf, 1); ++ sps->vui_parameters.bitstream_restriction_flag = read_bits(buf, 1); ++ ++ if (sps->vui_parameters.bitstream_restriction_flag) { ++ sps->vui_parameters.motion_vectors_over_pic_boundaries = read_bits(buf, 1); ++ sps->vui_parameters.max_bytes_per_pic_denom = read_exp_golomb(buf); ++ sps->vui_parameters.max_bits_per_mb_denom = read_exp_golomb(buf); ++ sps->vui_parameters.log2_max_mv_length_horizontal = read_exp_golomb(buf); ++ sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf); ++ sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf); ++ sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf); ++ } ++} ++ ++void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) ++{ ++ hrd->cpb_cnt_minus1 = read_exp_golomb(buf); ++ hrd->bit_rate_scale = read_bits(buf, 4); ++ hrd->cpb_size_scale = read_bits(buf, 4); ++ ++ int i; ++ for (i = 0; i <= hrd->cpb_cnt_minus1; i++) { ++ hrd->bit_rate_value_minus1[i] = read_exp_golomb(buf); ++ hrd->cpb_size_value_minus1[i] = read_exp_golomb(buf); ++ hrd->cbr_flag[i] = read_bits(buf, 1); ++ } ++ ++ hrd->initial_cpb_removal_delay_length_minus1 = read_bits(buf, 5); ++ hrd->cpb_removal_delay_length_minus1 = read_bits(buf, 5); ++ hrd->dpb_output_delay_length_minus1 = read_bits(buf, 5); ++ hrd->time_offset_length = read_bits(buf, 5); ++} ++ ++uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, ++ struct seq_parameter_set_rbsp *sps) ++{ ++ pps->pic_parameter_set_id = read_exp_golomb(buf); ++ pps->seq_parameter_set_id = read_exp_golomb(buf); ++ pps->entropy_coding_mode_flag = read_bits(buf, 1); ++ pps->pic_order_present_flag = read_bits(buf, 1); ++ ++ pps->num_slice_groups_minus1 = read_exp_golomb(buf); ++ if (pps->num_slice_groups_minus1 > 0) { ++ pps->slice_group_map_type = read_exp_golomb(buf); ++ if (pps->slice_group_map_type == 0) { ++ int i_group; ++ for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { ++ if (i_group < 64) ++ pps->run_length_minus1[i_group] = read_exp_golomb(buf); ++ else { // FIXME: skips if more than 64 groups exist ++ fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); ++ read_exp_golomb(buf); ++ } ++ } ++ } ++ else if (pps->slice_group_map_type == 3 || pps->slice_group_map_type == 4 ++ || pps->slice_group_map_type == 5) { ++ pps->slice_group_change_direction_flag = read_bits(buf, 1); ++ pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); ++ } ++ else if (pps->slice_group_map_type == 6) { ++ pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); ++ int i_group; ++ for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { ++ pps->slice_group_id[i_group] = read_bits(buf, ceil(log( ++ pps->num_slice_groups_minus1 + 1))); ++ } ++ } ++ } ++ ++ pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); ++ pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); ++ pps->weighted_pred_flag = read_bits(buf, 1); ++ pps->weighted_bipred_idc = read_bits(buf, 2); ++ pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); ++ pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); ++ pps->chroma_qp_index_offset = read_exp_golomb_s(buf); ++ pps->deblocking_filter_control_present_flag = read_bits(buf, 1); ++ pps->constrained_intra_pred_flag = read_bits(buf, 1); ++ pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); ++ ++ int bit_length = (buf->len*8)-rbsp_trailing_bits(buf->buf, buf->len); ++ int bit_read = bits_read(buf); ++ ++ memset(pps->scaling_lists_4x4, 16, sizeof(pps->scaling_lists_4x4)); ++ memset(pps->scaling_lists_8x8, 16, sizeof(pps->scaling_lists_8x8)); ++ if (bit_length-bit_read > 1) { ++ pps->transform_8x8_mode_flag = read_bits(buf, 1); ++ pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); ++ if (pps->pic_scaling_matrix_present_flag) { ++ int i; ++ for (i = 0; i < 8; i++) { ++ if(i < 6 || pps->transform_8x8_mode_flag) ++ pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); ++ else ++ pps->pic_scaling_list_present_flag[i] = 0; ++ ++ if (pps->pic_scaling_list_present_flag[i]) { ++ if (i < 6) ++ parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); ++ else ++ parse_scaling_list(buf, pps->scaling_lists_8x8[i - 6], 64, i); ++ } else { ++ pps_scaling_list_fallback(sps, pps, i); ++ } ++ } ++ } ++ ++ pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); ++ } else ++ pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset; ++ ++ if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { ++ memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, ++ sizeof(pps->scaling_lists_4x4)); ++ memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, ++ sizeof(pps->scaling_lists_8x8)); ++ } ++ ++ return 0; ++} ++ ++uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) ++{ ++ struct nal_unit *nal = parser->current_nal; ++ ++ struct seq_parameter_set_rbsp *sps = nal->sps; ++ struct pic_parameter_set_rbsp *pps = nal->pps; ++ struct slice_header *slc = nal->slc; ++ memset(slc, 0x00, sizeof(struct slice_header)); ++ if (!sps || !pps) ++ return -1; ++ ++ slc->first_mb_in_slice = read_exp_golomb(buf); ++ /* we do some parsing on the slice type, because the list is doubled */ ++ slc->slice_type = slice_type(read_exp_golomb(buf)); ++ ++ //print_slice_type(slc->slice_type); ++ slc->pic_parameter_set_id = read_exp_golomb(buf); ++ if(sps->separate_colour_plane_flag) ++ slc->colour_plane_id = read_bits(buf, 2); ++ ++ slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); ++ if (!sps->frame_mbs_only_flag) { ++ slc->field_pic_flag = read_bits(buf, 1); ++ if (slc->field_pic_flag) ++ slc->bottom_field_flag = read_bits(buf, 1); ++ else ++ slc->bottom_field_flag = 0; ++ } ++ else { ++ slc->field_pic_flag = 0; ++ slc->bottom_field_flag = 0; ++ } ++ ++ if (slc->field_pic_flag == 0) { ++ nal->max_pic_num = 1 << (sps->log2_max_frame_num_minus4+4); ++ nal->curr_pic_num = slc->frame_num; ++ } else { ++ nal->curr_pic_num = 2 * slc->frame_num + 1; ++ nal->max_pic_num = 2 * (1 << (sps->log2_max_frame_num_minus4+4)); ++ } ++ ++ if (nal->nal_unit_type == NAL_SLICE_IDR) ++ slc->idr_pic_id = read_exp_golomb(buf); ++ ++ if (!sps->pic_order_cnt_type) { ++ slc->pic_order_cnt_lsb = read_bits(buf, ++ sps->log2_max_pic_order_cnt_lsb_minus4 + 4); ++ if (pps->pic_order_present_flag && !slc->field_pic_flag) ++ slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); ++ } ++ ++ if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) { ++ slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); ++ if (pps->pic_order_present_flag && !slc->field_pic_flag) ++ slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); ++ } ++ ++ if (pps->redundant_pic_cnt_present_flag == 1) { ++ slc->redundant_pic_cnt = read_exp_golomb(buf); ++ } ++ ++ if (slc->slice_type == SLICE_B) ++ slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); ++ ++ /* take default values in case they are not set here */ ++ slc->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; ++ slc->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; ++ ++ if (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP ++ || slc->slice_type == SLICE_B) { ++ slc->num_ref_idx_active_override_flag = read_bits(buf, 1); ++ ++ if (slc->num_ref_idx_active_override_flag == 1) { ++ slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); ++ ++ if (slc->slice_type == SLICE_B) { ++ slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); ++ } ++ } ++ } ++ ++ /* --- ref_pic_list_reordering --- */ ++ parse_ref_pic_list_reordering(buf, nal, parser); ++ ++ /* --- pred_weight_table --- */ ++ if ((pps->weighted_pred_flag && (slc->slice_type == SLICE_P ++ || slc->slice_type == SLICE_SP)) || (pps->weighted_bipred_idc == 1 ++ && slc->slice_type == SLICE_B)) { ++ parse_pred_weight_table(buf, nal); ++ } ++ ++ /* --- dec_ref_pic_marking --- */ ++ if (nal->nal_ref_idc != 0) ++ parse_dec_ref_pic_marking(buf, parser); ++ else ++ slc->dec_ref_pic_marking_count = 0; ++ ++ return 0; ++} ++ ++void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, struct nal_parser *parser) ++{ ++ struct slice_header *slc = nal->slc; ++ ++ if (slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { ++ slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits( ++ buf, 1); ++ ++ if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) { ++ do { ++ slc->ref_pic_list_reordering.reordering_of_pic_nums_idc ++ = read_exp_golomb(buf); ++ ++ if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 ++ || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { ++ slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 ++ = read_exp_golomb(buf); ++ } ++ else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { ++ slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); ++ } ++ } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); ++ } ++ } ++ ++ if (slc->slice_type == SLICE_B) { ++ slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits( ++ buf, 1); ++ ++ if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) { ++ do { ++ slc->ref_pic_list_reordering.reordering_of_pic_nums_idc ++ = read_exp_golomb(buf); ++ ++ if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 ++ || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { ++ slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 ++ = read_exp_golomb(buf); ++ } ++ else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { ++ slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); ++ } ++ } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); ++ } ++ } ++} ++ ++void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) ++{ ++ struct seq_parameter_set_rbsp *sps = nal->sps; ++ struct pic_parameter_set_rbsp *pps = nal->pps; ++ struct slice_header *slc = nal->slc; ++ if (!sps || !pps) ++ return; ++ ++ nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf); ++ ++ uint32_t ChromaArrayType = sps->chroma_format_idc; ++ if(sps->separate_colour_plane_flag) ++ ChromaArrayType = 0; ++ ++ if (ChromaArrayType != 0) ++ nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); ++ ++ int i; ++ for (i = 0; i <= slc->num_ref_idx_l0_active_minus1; i++) { ++ uint8_t luma_weight_l0_flag = read_bits(buf, 1); ++ ++ if (luma_weight_l0_flag == 1) { ++ nal->slc->pred_weight_table.luma_weight_l0[i] = read_exp_golomb_s(buf); ++ nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf); ++ } ++ ++ if (ChromaArrayType != 0) { ++ uint8_t chroma_weight_l0_flag = read_bits(buf, 1); ++ ++ if (chroma_weight_l0_flag == 1) { ++ int j; ++ for (j = 0; j < 2; j++) { ++ nal->slc->pred_weight_table.chroma_weight_l0[i][j] ++ = read_exp_golomb_s(buf); ++ nal->slc->pred_weight_table.chroma_offset_l0[i][j] ++ = read_exp_golomb_s(buf); ++ } ++ } ++ } ++ } ++ ++ if ((slc->slice_type % 5) == SLICE_B) { ++ /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1 ++ * will break Divx7 files. Keep this in mind if any other streams are broken ++ */ ++ for (i = 0; i <= slc->num_ref_idx_l1_active_minus1; i++) { ++ uint8_t luma_weight_l1_flag = read_bits(buf, 1); ++ ++ if (luma_weight_l1_flag == 1) { ++ nal->slc->pred_weight_table.luma_weight_l1[i] = read_exp_golomb_s(buf); ++ nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf); ++ } ++ ++ if (ChromaArrayType != 0) { ++ uint8_t chroma_weight_l1_flag = read_bits(buf, 1); ++ ++ if (chroma_weight_l1_flag == 1) { ++ int j; ++ for (j = 0; j < 2; j++) { ++ nal->slc->pred_weight_table.chroma_weight_l1[i][j] ++ = read_exp_golomb_s(buf); ++ nal->slc->pred_weight_table.chroma_offset_l1[i][j] ++ = read_exp_golomb_s(buf); ++ } ++ } ++ } ++ } ++ } ++} ++ ++void decode_ref_pic_marking(struct nal_unit *nal, ++ uint32_t memory_management_control_operation, ++ uint32_t marking_nr, ++ struct nal_parser *parser) ++{ ++ struct slice_header *slc = nal->slc; ++ struct dpb *dpb = &parser->dpb; ++ if (!slc) ++ return; ++ ++ if (memory_management_control_operation == 1) { ++ // short-term -> unused for reference ++ uint32_t pic_num_x = (nal->curr_pic_num ++ - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1))%nal->max_pic_num; ++ struct decoded_picture* pic = NULL; ++ if ((pic = dpb_get_picture(dpb, pic_num_x)) != NULL) { ++ if (pic->nal->slc->field_pic_flag == 0) { ++ dpb_set_unused_ref_picture_a(dpb, pic); ++ } else { ++ //if(!pic->top_is_reference) ++ dpb_set_unused_ref_picture_a(dpb, pic); ++ /*else ++ pic->top_is_reference = 0;*/ ++ ++ //printf("FIXME: We might need do delete more from the DPB...\n"); ++ // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 ++ } ++ } ++ } else if (memory_management_control_operation == 2) { ++ // long-term -> unused for reference ++ struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, ++ slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); ++ if (pic != NULL) { ++ if (pic->nal->slc->field_pic_flag == 0) ++ dpb_set_unused_ref_picture(dpb, ++ slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); ++ else { ++ dpb_set_unused_ref_picture(dpb, ++ slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); ++ printf("FIXME: We might need do delete more from the DPB...\n"); ++ } ++ } ++ } else if (memory_management_control_operation == 3) { ++ // short-term -> long-term, set long-term frame index ++ uint32_t pic_num_x = nal->curr_pic_num ++ - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1); ++ struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, ++ slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); ++ if (pic != NULL) ++ dpb_set_unused_ref_picture_bylidx(dpb, ++ slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx); ++ ++ pic = dpb_get_picture(dpb, pic_num_x); ++ if (pic) { ++ if (pic->nal->slc->field_pic_flag == 0) { ++ pic = dpb_get_picture(dpb, pic_num_x); ++ pic->nal->long_term_frame_idx ++ = slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx; ++ } ++ else ++ printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x); ++ } ++ else { ++ printf("memory_management_control_operation: 3 failed. No such picture.\n"); ++ } ++ ++ } else if (memory_management_control_operation == 4) { ++ // set max-long-term frame index, ++ // mark all long-term pictures with long-term frame idx ++ // greater max-long-term farme idx as unused for ref ++ if (slc->dec_ref_pic_marking[marking_nr].max_long_term_frame_idx_plus1 == 0) ++ dpb_set_unused_ref_picture_lidx_gt(dpb, 0); ++ else ++ dpb_set_unused_ref_picture_lidx_gt(dpb, ++ slc->dec_ref_pic_marking[marking_nr].max_long_term_frame_idx_plus1 - 1); ++ } else if (memory_management_control_operation == 5) { ++ // mark all ref pics as unused for reference, ++ // set max-long-term frame index = no long-term frame idxs ++ dpb_flush(dpb); ++ parser->pic_order_cnt_lsb = 0; ++ parser->pic_order_cnt_msb = 0; ++ parser->prev_pic_order_cnt_lsb = 0; ++ parser->prev_pic_order_cnt_msb = 0; ++ } else if (memory_management_control_operation == 6) { ++ // mark current picture as used for long-term ref, ++ // assing long-term frame idx to it ++ struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, ++ slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx); ++ if (pic != NULL) ++ dpb_set_unused_ref_picture_bylidx(dpb, ++ slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx); ++ ++ nal->long_term_frame_idx = slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx; ++ ++ if (slc->field_pic_flag == 0) { ++ nal->used_for_long_term_ref = 1; ++ } ++ else ++ printf("FIXME: BY Set frame to long-term ref\n"); ++ } ++ /* FIXME: Do we need to care about MMC=0? */ ++} ++ ++void parse_dec_ref_pic_marking(struct buf_reader *buf, ++ struct nal_parser *parser) ++{ ++ struct nal_unit *nal = parser->current_nal; ++ struct pic_parameter_set_rbsp *pps = parser->current_nal->pps; ++ struct slice_header *slc = nal->slc; ++ ++ if (!slc || !pps) ++ return; ++ ++ slc->dec_ref_pic_marking_count = 0; ++ int i = slc->dec_ref_pic_marking_count; ++ ++ if (nal->nal_unit_type == NAL_SLICE_IDR) { ++ slc->dec_ref_pic_marking[i].no_output_of_prior_pics_flag = read_bits(buf, 1); ++ slc->dec_ref_pic_marking[i].long_term_reference_flag = read_bits(buf, 1); ++ } else { ++ slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag = read_bits( ++ buf, 1); ++ ++ if (slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag) { ++ do { ++ slc->dec_ref_pic_marking[i].memory_management_control_operation ++ = read_exp_golomb(buf); ++ ++ if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 1 ++ || slc->dec_ref_pic_marking[i].memory_management_control_operation ++ == 3) ++ slc->dec_ref_pic_marking[i].difference_of_pic_nums_minus1 ++ = read_exp_golomb(buf); ++ ++ if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 2) ++ slc->dec_ref_pic_marking[i].long_term_pic_num = read_exp_golomb(buf); ++ ++ if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 3 ++ || slc->dec_ref_pic_marking[i].memory_management_control_operation ++ == 6) ++ slc->dec_ref_pic_marking[i].long_term_frame_idx = read_exp_golomb(buf); ++ ++ if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 4) ++ slc->dec_ref_pic_marking[i].max_long_term_frame_idx_plus1 ++ = read_exp_golomb(buf); ++ ++ i++; ++ if(i >= 10) { ++ printf("Error: Not more than 10 MMC operations supported per slice. Dropping some.\n"); ++ i = 0; ++ } ++ } while (slc->dec_ref_pic_marking[i-1].memory_management_control_operation ++ != 0); ++ } ++ } ++ ++ slc->dec_ref_pic_marking_count = (i>0) ? (i-1) : 0; ++} ++ ++/* ----------------- NAL parser ----------------- */ ++ ++struct nal_parser* init_parser() ++{ ++ struct nal_parser *parser = calloc(1, sizeof(struct nal_parser)); ++ parser->nal0 = init_nal_unit(); ++ parser->nal1 = init_nal_unit(); ++ parser->current_nal = parser->nal0; ++ parser->last_nal = parser->nal1; ++ parser->slice_cnt = 1; ++ ++ parser->field = -1; ++ ++ /* no idea why we do that. inspired by libavcodec, ++ * as we couldn't figure in the specs.... ++ */ ++ parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_lsb = 1 << 16; ++ ++ return parser; ++} ++ ++void free_parser(struct nal_parser *parser) ++{ ++ free_nal_unit(parser->nal0); ++ free_nal_unit(parser->nal1); ++ free(parser); ++} ++ ++void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len) ++{ ++ struct buf_reader bufr; ++ ++ bufr.buf = inbuf; ++ bufr.cur_pos = inbuf; ++ bufr.cur_offset = 8; ++ bufr.len = inbuf_len; ++ ++ struct nal_unit *nal = parser->current_nal; ++ struct nal_unit *nal1 = parser->last_nal; ++ ++ if (!nal->sps) ++ nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); ++ else ++ memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); ++ ++ /* reserved */ ++ read_bits(&bufr, 8); ++ nal->sps->profile_idc = read_bits(&bufr, 8); ++ read_bits(&bufr, 8); ++ nal->sps->level_idc = read_bits(&bufr, 8); ++ read_bits(&bufr, 6); ++ ++ parser->nal_size_length = read_bits(&bufr, 2) + 1; ++ parser->nal_size_length_buf = calloc(1, parser->nal_size_length); ++ read_bits(&bufr, 3); ++ uint8_t sps_count = read_bits(&bufr, 5); ++ ++ inbuf += 6; ++ inbuf_len -= 6; ++ int i; ++ for(i = 0; i < sps_count; i++) { ++ uint16_t sps_size = read_bits(&bufr, 16); ++ inbuf += 2; ++ inbuf_len -= 2; ++ parse_nal(inbuf, sps_size, parser); ++ inbuf += sps_size; ++ inbuf_len -= sps_size; ++ } ++ ++ bufr.buf = inbuf; ++ bufr.cur_pos = inbuf; ++ bufr.cur_offset = 8; ++ bufr.len = inbuf_len; ++ ++ uint8_t pps_count = read_bits(&bufr, 8); ++ inbuf += 1; ++ for(i = 0; i < pps_count; i++) { ++ uint16_t pps_size = read_bits(&bufr, 16); ++ inbuf += 2; ++ inbuf_len -= 2; ++ parse_nal(inbuf, pps_size, parser); ++ inbuf += pps_size; ++ inbuf_len -= pps_size; ++ } ++ ++ copy_nal_unit(nal1, nal); ++ printf("done parsing extradata\n"); ++} ++ ++void process_mmc_operations(struct nal_parser *parser) ++{ ++ if(parser->last_nal_res == 1 && parser->current_nal && ++ parser->current_nal->slc) { ++ int i; ++ for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) { ++ decode_ref_pic_marking( ++ parser->current_nal, ++ parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, ++ i, ++ parser); ++ } ++ ++ if (parser->last_nal->slc != NULL) ++ parser->prev_pic_order_cnt_lsb ++ = parser->last_nal->slc->pic_order_cnt_lsb; ++ parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; ++ } ++} ++ ++int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, ++ uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) ++{ ++ int32_t next_nal = 0; ++ int32_t offset = 0; ++ int start_seq_len = 3; ++ ++ if(parser->nal_size_length > 0) ++ start_seq_len = offset = parser->nal_size_length; ++ ++ if (parser->prebuf_len + inbuf_len > MAX_FRAME_SIZE) { ++ printf("buf underrun!!\n"); ++ *ret_len = 0; ++ *ret_buf = NULL; ++ parser->prebuf_len = 0; ++ return inbuf_len; ++ } ++ ++ /* copy the whole inbuf to the prebuf, ++ * then search for a nal-start sequence in the prebuf, ++ * if it's in there, parse the nal and append to parser->buf ++ * or return a frame */ ++ ++ xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len); ++ parser->prebuf_len += inbuf_len; ++ ++ while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-start_seq_len+offset, parser)) > 0) { ++ ++ if(!parser->nal_size_length && ++ (parser->prebuf[0] != 0x00 || parser->prebuf[1] != 0x00 || parser->prebuf[2] != 0x01)) { ++ printf("Broken NAL, skip it.\n"); ++ parser->last_nal_res = 2; ++ } else ++ parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, next_nal, parser); ++ ++ if ((parser->last_nal_res == 1 || parser->last_nal_res == 3) && parser->buf_len > 0) { ++ ++ //printf("Frame complete: %d bytes\n", parser->buf_len); ++ *ret_len = parser->buf_len; ++ *ret_buf = malloc(*ret_len); ++ xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); ++ *ret_slice_cnt = parser->slice_cnt; ++ ++ parser->slice_cnt = 1; ++ parser->buf_len = 0; ++ ++ /* this is a SLICE, keep it in the buffer */ ++ ++ if(parser->last_nal_res != 3) { ++ if(parser->nal_size_length > 0) { ++ static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; ++ xine_fast_memcpy(parser->buf, start_seq, 3); ++ parser->buf_len += 3; ++ } ++ ++ xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); ++ parser->buf_len += next_nal+start_seq_len-2*offset; ++ } ++ ++ memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); ++ parser->prebuf_len -= next_nal+start_seq_len-offset; ++ ++ return inbuf_len; ++ } ++ ++ /* got a new nal, which is part of the current ++ * coded picture. add it to buf ++ */ ++ if (parser->last_nal_res < 2) { ++ if (parser->buf_len + next_nal+start_seq_len-offset > MAX_FRAME_SIZE) { ++ printf("buf underrun 1!!\n"); ++ parser->buf_len = 0; ++ *ret_len = 0; ++ *ret_buf = NULL; ++ return inbuf_len; ++ } ++ ++ if(parser->nal_size_length > 0) { ++ static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; ++ xine_fast_memcpy(parser->buf+parser->buf_len, start_seq, 3); ++ parser->buf_len += 3; ++ } ++ ++ xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); ++ parser->buf_len += next_nal+start_seq_len-2*offset; ++ ++ memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); ++ parser->prebuf_len -= next_nal+start_seq_len-offset; ++ } else { ++ /* got a non-relevant nal, just remove it */ ++ memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); ++ parser->prebuf_len -= next_nal+start_seq_len-offset; ++ } ++ } ++ ++ *ret_buf = NULL; ++ *ret_len = 0; ++ return inbuf_len; ++} ++ ++ ++/** ++ * @return 0: NAL is part of coded picture ++ * 2: NAL is not part of coded picture ++ * 1: NAL is the beginning of a new coded picture ++ * 3: NAL is marked as END_OF_SEQUENCE ++ */ ++int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) ++{ ++ struct buf_reader bufr; ++ ++ bufr.buf = buf; ++ bufr.cur_pos = buf; ++ bufr.cur_offset = 8; ++ bufr.len = buf_len; ++ ++ struct nal_unit *nal = parser->current_nal; ++ struct nal_unit *last_nal = parser->last_nal; ++ ++ int res = parse_nal_header(&bufr, parser); ++ if (res == NAL_SLICE_IDR) { ++ parser->is_idr = 1; ++ } ++ ++ calculate_pic_order(parser); ++ ++ if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) { ++ // now detect if it's a new frame! ++ int ret = 0; ++ uint8_t reason = 0; ++ if (nal->slc->field_pic_flag == 1) ++ parser->field = nal->slc->bottom_field_flag; ++ else { ++ parser->have_top = 1; ++ parser->field = -1; ++ } ++ ++ if (nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) ++ parser->have_top = 1; ++ ++ parser->slice = 1; ++ ++ if (nal->slc == NULL || last_nal->slc == NULL) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->slc && last_nal->slc && (nal->slc->frame_num ++ != last_nal->slc->frame_num)) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->slc && last_nal->slc && (nal->slc->pic_parameter_set_id ++ != last_nal->slc->pic_parameter_set_id)) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->slc && last_nal->slc && (nal->slc->field_pic_flag ++ != last_nal->slc->field_pic_flag)) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->slc && last_nal->slc && nal->slc->bottom_field_flag ++ != last_nal->slc->bottom_field_flag) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->nal_ref_idc != last_nal->nal_ref_idc && (nal->nal_ref_idc == 0 ++ || last_nal->nal_ref_idc == 0)) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->sps && nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type ++ == 0 && last_nal->sps->pic_order_cnt_type == 0 ++ && (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb ++ || nal->slc->delta_pic_order_cnt_bottom ++ != last_nal->slc->delta_pic_order_cnt_bottom))) { ++ ret = 1; ++ reason++; ++ /*printf("C: Reason: %d, %d, %d\n", res, nal->slc->pic_order_cnt_lsb, ++ last_nal->slc->pic_order_cnt_lsb);*/ ++ } ++ if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 ++ && last_nal->sps->pic_order_cnt_type == 1 ++ && (nal->slc->delta_pic_order_cnt[0] ++ != last_nal->slc->delta_pic_order_cnt[0] ++ || nal->slc->delta_pic_order_cnt[1] ++ != last_nal->slc->delta_pic_order_cnt[1]))) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->nal_unit_type != last_nal->nal_unit_type && (nal->nal_unit_type ++ == 5 || last_nal->nal_unit_type == 5)) { ++ ret = 1; ++ reason++; ++ } ++ if (nal->slc && last_nal->slc && (nal->nal_unit_type == 5 ++ && last_nal->nal_unit_type == 5 && nal->slc->idr_pic_id ++ != last_nal->slc->idr_pic_id)) { ++ ret = 1; ++ reason++; ++ } ++ ++ if (parser->current_nal == parser->nal0) { ++ parser->current_nal = parser->nal1; ++ parser->last_nal = parser->nal0; ++ } ++ else { ++ parser->current_nal = parser->nal0; ++ parser->last_nal = parser->nal1; ++ } ++ ++ if(!parser->current_nal->sps && parser->last_nal->sps) { ++ parser->current_nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); ++ xine_fast_memcpy(parser->current_nal->sps, parser->last_nal->sps, sizeof(struct seq_parameter_set_rbsp)); ++ } ++ ++ if(!parser->current_nal->pps && parser->last_nal->pps) { ++ parser->current_nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); ++ xine_fast_memcpy(parser->current_nal->pps, parser->last_nal->pps, sizeof(struct pic_parameter_set_rbsp)); ++ } ++ ++ /* increase the slice_cnt until a new frame is detected */ ++ if (!ret) ++ parser->slice_cnt++; ++ ++ return ret; ++ } else if (res == NAL_PPS || res == NAL_SPS) { ++ return 2; ++ } else if (res == NAL_END_OF_SEQUENCE) { ++ if (parser->current_nal == parser->nal0) { ++ parser->current_nal = parser->nal1; ++ parser->last_nal = parser->nal0; ++ } ++ else { ++ parser->current_nal = parser->nal0; ++ parser->last_nal = parser->nal1; ++ } ++ ++ return 3; ++ } else if (res >= NAL_SEI) { ++ return 2; ++ } ++ ++ return 0; ++} ++ ++int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) ++{ ++ if(buf_len <= 0) ++ return -1; ++ ++ if(parser->nal_size_length > 0) { ++ if(buf_len < parser->nal_size_length) { ++ return -1; ++ } ++ ++ uint32_t next_nal = parser->next_nal_position; ++ if(!next_nal) { ++ struct buf_reader bufr; ++ ++ bufr.buf = buf; ++ bufr.cur_pos = buf; ++ bufr.cur_offset = 8; ++ bufr.len = buf_len; ++ ++ next_nal = read_bits(&bufr, parser->nal_size_length*8)+parser->nal_size_length; ++ } ++ ++ if(next_nal > buf_len) { ++ parser->next_nal_position = next_nal; ++ return -1; ++ } else ++ parser->next_nal_position = 0; ++ ++ return next_nal; ++ } ++ ++ /* NAL_END_OF_SEQUENCE has only 1 byte, so ++ * we do not need to search for the next start sequence */ ++ if(buf[0] == NAL_END_OF_SEQUENCE) ++ return 1; ++ ++ int i; ++ for (i = 0; i < buf_len - 2; i++) { ++ if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x01) { ++ //printf("found nal at: %d\n", i); ++ return i; ++ } ++ } ++ ++ return -1; ++} +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/vdpau_mpeg12.c +@@ -0,0 +1,1027 @@ ++/* ++ * Copyright (C) 2008 the xine project ++ * Copyright (C) 2008 Christophe Thommeret ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ * ++ * vdpau_mpeg12.c, a mpeg1/2 video stream parser using VDPAU hardware decoder ++ * ++ */ ++ ++/*#define LOG*/ ++#define LOG_MODULE "vdpau_mpeg12" ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "xine_internal.h" ++#include "video_out.h" ++#include "buffer.h" ++#include "xineutils.h" ++#include "accel_vdpau.h" ++#include "bits_reader.h" ++ ++#include ++ ++#define sequence_header_code 0xb3 ++#define sequence_error_code 0xb4 ++#define sequence_end_code 0xb7 ++#define group_start_code 0xb8 ++#define extension_start_code 0xb5 ++#define user_data_start_code 0xb2 ++#define picture_start_code 0x00 ++#define begin_slice_start_code 0x01 ++#define end_slice_start_code 0xaf ++ ++#define sequence_ext_sc 1 ++#define quant_matrix_ext_sc 3 ++#define picture_coding_ext_sc 8 ++#define sequence_display_ext_sc 2 ++ ++#define I_FRAME 1 ++#define P_FRAME 2 ++#define B_FRAME 3 ++ ++#define PICTURE_TOP 1 ++#define PICTURE_BOTTOM 2 ++#define PICTURE_FRAME 3 ++ ++#define WANT_HEADER 1 ++#define WANT_EXT 2 ++#define WANT_SLICE 3 ++ ++/*#define MAKE_DAT*/ /*do NOT define this, unless you know what you do */ ++#ifdef MAKE_DAT ++static int nframes; ++static FILE *outfile; ++#endif ++ ++ ++ ++/* default intra quant matrix, in zig-zag order */ ++static const uint8_t default_intra_quantizer_matrix[64] = { ++ 8, ++ 16, 16, ++ 19, 16, 19, ++ 22, 22, 22, 22, ++ 22, 22, 26, 24, 26, ++ 27, 27, 27, 26, 26, 26, ++ 26, 27, 27, 27, 29, 29, 29, ++ 34, 34, 34, 29, 29, 29, 27, 27, ++ 29, 29, 32, 32, 34, 34, 37, ++ 38, 37, 35, 35, 34, 35, ++ 38, 38, 40, 40, 40, ++ 48, 48, 46, 46, ++ 56, 56, 58, ++ 69, 69, ++ 83 ++}; ++ ++uint8_t mpeg2_scan_norm[64] = { ++ /* Zig-Zag scan pattern */ ++ 0, 1, 8,16, 9, 2, 3,10, ++ 17,24,32,25,18,11, 4, 5, ++ 12,19,26,33,40,48,41,34, ++ 27,20,13, 6, 7,14,21,28, ++ 35,42,49,56,57,50,43,36, ++ 29,22,15,23,30,37,44,51, ++ 58,59,52,45,38,31,39,46, ++ 53,60,61,54,47,55,62,63 ++}; ++ ++ ++ ++typedef struct { ++ VdpPictureInfoMPEG1Or2 vdp_infos; /* first field, also used for frame */ ++ VdpPictureInfoMPEG1Or2 vdp_infos2; /* second field */ ++ int slices_count, slices_count2; ++ uint8_t *slices; ++ int slices_size; ++ int slices_pos, slices_pos_top; ++ ++ int progressive_frame; ++ int state; ++} picture_t; ++ ++ ++ ++typedef struct { ++ uint32_t coded_width; ++ uint32_t coded_height; ++ ++ uint64_t video_step; /* frame duration in pts units */ ++ double ratio; ++ VdpDecoderProfile profile; ++ int chroma; ++ int top_field_first; ++ ++ int have_header; ++ ++ uint8_t *buf; /* accumulate data */ ++ int bufseek; ++ uint32_t bufsize; ++ uint32_t bufpos; ++ int start; ++ ++ picture_t picture; ++ vo_frame_t *forward_ref; ++ vo_frame_t *backward_ref; ++ ++ int64_t cur_pts, seq_pts; ++ ++ vdpau_accel_t *accel_vdpau; ++ ++ bits_reader_t br; ++ ++ int vdp_runtime_nr; ++ ++} sequence_t; ++ ++ ++ ++typedef struct { ++ video_decoder_class_t decoder_class; ++} vdpau_mpeg12_class_t; ++ ++ ++ ++typedef struct vdpau_mpeg12_decoder_s { ++ video_decoder_t video_decoder; /* parent video decoder structure */ ++ ++ vdpau_mpeg12_class_t *class; ++ xine_stream_t *stream; ++ ++ sequence_t sequence; ++ ++ VdpDecoder decoder; ++ VdpDecoderProfile decoder_profile; ++ uint32_t decoder_width; ++ uint32_t decoder_height; ++ ++} vdpau_mpeg12_decoder_t; ++ ++ ++ ++static void reset_picture( picture_t *pic ) ++{ ++ lprintf( "reset_picture\n" ); ++ pic->vdp_infos.picture_structure = 0; ++ pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0; ++ pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1; ++ pic->vdp_infos2.concealment_motion_vectors = pic->vdp_infos.concealment_motion_vectors = 0; ++ pic->vdp_infos2.intra_vlc_format = pic->vdp_infos.intra_vlc_format = 0; ++ pic->vdp_infos2.alternate_scan = pic->vdp_infos.alternate_scan = 0; ++ pic->vdp_infos2.q_scale_type = pic->vdp_infos.q_scale_type = 0; ++ pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 1; ++ pic->slices_count = 0; ++ pic->slices_count2 = 0; ++ pic->slices_pos = 0; ++ pic->slices_pos_top = 0; ++ pic->progressive_frame = 0; ++ pic->state = WANT_HEADER; ++} ++ ++ ++ ++static void init_picture( picture_t *pic ) ++{ ++ pic->slices_size = 2048; ++ pic->slices = (uint8_t*)malloc(pic->slices_size); ++ reset_picture( pic ); ++} ++ ++ ++ ++static void reset_sequence( sequence_t *sequence, int free_refs ) ++{ ++ sequence->cur_pts = sequence->seq_pts = 0; ++ if ( sequence->forward_ref ) ++ sequence->forward_ref->pts = 0; ++ if ( sequence->backward_ref ) ++ sequence->backward_ref->pts = 0; ++ ++ if ( !free_refs ) ++ return; ++ ++ sequence->bufpos = 0; ++ sequence->bufseek = 0; ++ sequence->start = -1; ++ if ( sequence->forward_ref ) ++ sequence->forward_ref->free( sequence->forward_ref ); ++ sequence->forward_ref = NULL; ++ if ( sequence->backward_ref ) ++ sequence->backward_ref->free( sequence->backward_ref ); ++ sequence->backward_ref = NULL; ++ sequence->top_field_first = 0; ++} ++ ++ ++ ++static void free_sequence( sequence_t *sequence ) ++{ ++ lprintf( "init_sequence\n" ); ++ sequence->have_header = 0; ++ sequence->profile = VDP_DECODER_PROFILE_MPEG1; ++ sequence->chroma = 0; ++ sequence->video_step = 3600; ++ reset_sequence( sequence, 1 ); ++} ++ ++ ++ ++static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ ++ int i, j; ++ ++ if ( sequence->cur_pts ) { ++ sequence->seq_pts = sequence->cur_pts; ++ } ++ ++ bits_reader_set( &sequence->br, buf ); ++ sequence->coded_width = read_bits( &sequence->br, 12 ); ++ lprintf( "coded_width: %d\n", sequence->coded_width ); ++ sequence->coded_height = read_bits( &sequence->br, 12 ); ++ lprintf( "coded_height: %d\n", sequence->coded_height ); ++ int rt = read_bits( &sequence->br, 4 ); ++ switch ( rt ) { ++ case 1: sequence->ratio = 1.0; break; ++ case 2: sequence->ratio = 4.0/3.0; break; ++ case 3: sequence->ratio = 16.0/9.0; break; ++ case 4: sequence->ratio = 2.21; break; ++ default: sequence->ratio = (double)sequence->coded_width/(double)sequence->coded_height; ++ } ++ lprintf( "ratio: %d\n", rt ); ++ int fr = read_bits( &sequence->br, 4 ); ++ switch ( fr ) { ++ case 1: sequence->video_step = 3913; break; /* 23.976.. */ ++ case 2: sequence->video_step = 3750; break; /* 24 */ ++ case 3: sequence->video_step = 3600; break; /* 25 */ ++ case 4: sequence->video_step = 3003; break; /* 29.97.. */ ++ case 5: sequence->video_step = 3000; break; /* 30 */ ++ case 6: sequence->video_step = 1800; break; /* 50 */ ++ case 7: sequence->video_step = 1525; break; /* 59.94.. */ ++ case 8: sequence->video_step = 1509; break; /* 60 */ ++ } ++ lprintf( "frame_rate: %d\n", fr ); ++ int tmp; ++ tmp = read_bits( &sequence->br, 18 ); ++ lprintf( "bit_rate_value: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 1 ); ++ lprintf( "marker_bit: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 10 ); ++ lprintf( "vbv_buffer_size_value: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 1 ); ++ lprintf( "constrained_parameters_flag: %d\n", tmp ); ++ i = read_bits( &sequence->br, 1 ); ++ lprintf( "load_intra_quantizer_matrix: %d\n", i ); ++ if ( i ) { ++ for ( j=0; j<64; ++j ) { ++ sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); ++ } ++ } ++ else { ++ for ( j=0; j<64; ++j ) { ++ sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = default_intra_quantizer_matrix[j]; ++ } ++ } ++ ++ i = read_bits( &sequence->br, 1 ); ++ lprintf( "load_non_intra_quantizer_matrix: %d\n", i ); ++ if ( i ) { ++ for ( j=0; j<64; ++j ) { ++ sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); ++ } ++ } ++ else { ++ memset( sequence->picture.vdp_infos.non_intra_quantizer_matrix, 16, 64 ); ++ memset( sequence->picture.vdp_infos2.non_intra_quantizer_matrix, 16, 64 ); ++ } ++ ++ if ( !sequence->have_header ) { ++ sequence->have_header = 1; ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); ++ _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); ++ _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "MPEG1/2 (vdpau)" ); ++ xine_event_t event; ++ xine_format_change_data_t data; ++ event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; ++ event.stream = this_gen->stream; ++ event.data = &data; ++ event.data_length = sizeof(data); ++ data.width = sequence->coded_width; ++ data.height = sequence->coded_height; ++ data.aspect = sequence->ratio; ++ xine_event_send( this_gen->stream, &event ); ++ } ++} ++ ++ ++ ++static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) ++{ ++ if ( sequence->picture.state!=WANT_HEADER ) ++ return; ++ ++ if ( sequence->cur_pts ) { ++ sequence->seq_pts = sequence->cur_pts; ++ } ++ ++ if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 ) ++ sequence->picture.vdp_infos.picture_structure = PICTURE_FRAME; ++ ++ VdpPictureInfoMPEG1Or2 *infos = &sequence->picture.vdp_infos; ++ ++ if ( sequence->picture.vdp_infos.picture_structure && sequence->picture.slices_count2 ) ++ reset_picture( &sequence->picture ); ++ ++ if ( sequence->picture.vdp_infos.picture_structure==PICTURE_FRAME ) { ++ reset_picture( &sequence->picture ); ++ } ++ else if ( sequence->picture.vdp_infos.picture_structure ) { ++ infos = &sequence->picture.vdp_infos2; ++ } ++ ++ bits_reader_set( &sequence->br, buf ); ++ int tmp = read_bits( &sequence->br, 10 ); ++ lprintf( "temporal_reference: %d\n", tmp ); ++ infos->picture_coding_type = read_bits( &sequence->br, 3 ); ++ lprintf( "picture_coding_type: %d\n", infos->picture_coding_type ); ++ infos->forward_reference = VDP_INVALID_HANDLE; ++ infos->backward_reference = VDP_INVALID_HANDLE; ++ read_bits( &sequence->br, 16 ); ++ if ( infos->picture_coding_type > I_FRAME ) { ++ infos->full_pel_forward_vector = read_bits( &sequence->br, 1 ); ++ infos->f_code[0][0] = infos->f_code[0][1] = read_bits( &sequence->br, 3 ); ++ if ( infos->picture_coding_type==B_FRAME ) { ++ infos->full_pel_backward_vector = read_bits( &sequence->br, 1 ); ++ infos->f_code[1][0] = infos->f_code[1][1] = read_bits( &sequence->br, 3 ); ++ } ++ } ++ else { ++ infos->full_pel_forward_vector = 0; ++ infos->full_pel_backward_vector = 0; ++ } ++ if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 ) ++ sequence->picture.state = WANT_SLICE; ++ else ++ sequence->picture.state = WANT_EXT; ++} ++ ++ ++ ++static void sequence_extension( sequence_t *sequence, uint8_t *buf, int len ) ++{ ++ bits_reader_set( &sequence->br, buf ); ++ int tmp = read_bits( &sequence->br, 4 ); ++ lprintf( "extension_start_code_identifier: %d\n", tmp ); ++ read_bits( &sequence->br, 1 ); ++ switch ( read_bits( &sequence->br, 3 ) ) { ++ case 5: sequence->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; break; ++ default: sequence->profile = VDP_DECODER_PROFILE_MPEG2_MAIN; ++ } ++ read_bits( &sequence->br, 4 ); ++ tmp = read_bits( &sequence->br, 1 ); ++ lprintf( "progressive_sequence: %d\n", tmp ); ++ if ( read_bits( &sequence->br, 2 ) == 2 ) ++ sequence->chroma = VO_CHROMA_422; ++ tmp = read_bits( &sequence->br, 2 ); ++ lprintf( "horizontal_size_extension: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 2 ); ++ lprintf( "vertical_size_extension: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 12 ); ++ lprintf( "bit_rate_extension: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 1 ); ++ lprintf( "marker_bit: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 8 ); ++ lprintf( "vbv_buffer_size_extension: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 1 ); ++ lprintf( "low_delay: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 2 ); ++ lprintf( "frame_rate_extension_n: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 5 ); ++ lprintf( "frame_rate_extension_d: %d\n", tmp ); ++} ++ ++ ++ ++static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int len ) ++{ ++ if ( sequence->picture.state!=WANT_EXT ) ++ return; ++ ++ VdpPictureInfoMPEG1Or2 *infos = &sequence->picture.vdp_infos; ++ if ( infos->picture_structure && infos->picture_structure!=PICTURE_FRAME ) ++ infos = &sequence->picture.vdp_infos2; ++ ++ bits_reader_set( &sequence->br, buf ); ++ int tmp = read_bits( &sequence->br, 4 ); ++ lprintf( "extension_start_code_identifier: %d\n", tmp ); ++ infos->f_code[0][0] = read_bits( &sequence->br, 4 ); ++ infos->f_code[0][1] = read_bits( &sequence->br, 4 ); ++ infos->f_code[1][0] = read_bits( &sequence->br, 4 ); ++ infos->f_code[1][1] = read_bits( &sequence->br, 4 ); ++ lprintf( "f_code_0_0: %d\n", infos->f_code[0][0] ); ++ lprintf( "f_code_0_1: %d\n", infos->f_code[0][1] ); ++ lprintf( "f_code_1_0: %d\n", infos->f_code[1][0] ); ++ lprintf( "f_code_1_1: %d\n", infos->f_code[1][1] ); ++ infos->intra_dc_precision = read_bits( &sequence->br, 2 ); ++ lprintf( "intra_dc_precision: %d\n", infos->intra_dc_precision ); ++ infos->picture_structure = read_bits( &sequence->br, 2 ); ++ lprintf( "picture_structure: %d\n", infos->picture_structure ); ++ infos->top_field_first = read_bits( &sequence->br, 1 ); ++ lprintf( "top_field_first: %d\n", infos->top_field_first ); ++ infos->frame_pred_frame_dct = read_bits( &sequence->br, 1 ); ++ lprintf( "frame_pred_frame_dct: %d\n", infos->frame_pred_frame_dct ); ++ infos->concealment_motion_vectors = read_bits( &sequence->br, 1 ); ++ lprintf( "concealment_motion_vectors: %d\n", infos->concealment_motion_vectors ); ++ infos->q_scale_type = read_bits( &sequence->br, 1 ); ++ lprintf( "q_scale_type: %d\n", infos->q_scale_type ); ++ infos->intra_vlc_format = read_bits( &sequence->br, 1 ); ++ lprintf( "intra_vlc_format: %d\n", infos->intra_vlc_format ); ++ infos->alternate_scan = read_bits( &sequence->br, 1 ); ++ lprintf( "alternate_scan: %d\n", infos->alternate_scan ); ++ tmp = read_bits( &sequence->br, 1 ); ++ lprintf( "repeat_first_field: %d\n", tmp ); ++ tmp = read_bits( &sequence->br, 1 ); ++ lprintf( "chroma_420_type: %d\n", tmp ); ++ sequence->picture.progressive_frame = read_bits( &sequence->br, 1 ); ++ lprintf( "progressive_frame: %d\n", sequence->picture.progressive_frame ); ++ sequence->picture.state = WANT_SLICE; ++} ++ ++ ++ ++static void quant_matrix_extension( sequence_t *sequence, uint8_t *buf, int len ) ++{ ++ int i, j; ++ ++ bits_reader_set( &sequence->br, buf ); ++ read_bits( &sequence->br, 4 ); ++ i = read_bits( &sequence->br, 1 ); ++ lprintf( "load_intra_quantizer_matrix: %d\n", i ); ++ if ( i ) { ++ for ( j=0; j<64; ++j ) { ++ sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); ++ } ++ } ++ else { ++ for ( j=0; j<64; ++j ) { ++ sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = default_intra_quantizer_matrix[j]; ++ } ++ } ++ ++ i = read_bits( &sequence->br, 1 ); ++ lprintf( "load_non_intra_quantizer_matrix: %d\n", i ); ++ if ( i ) { ++ for ( j=0; j<64; ++j ) { ++ sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); ++ } ++ } ++ else { ++ memset( sequence->picture.vdp_infos.non_intra_quantizer_matrix, 16, 64 ); ++ memset( sequence->picture.vdp_infos2.non_intra_quantizer_matrix, 16, 64 ); ++ } ++} ++ ++ ++ ++static void copy_slice( sequence_t *sequence, uint8_t *buf, int len ) ++{ ++ int size = sequence->picture.slices_pos+len; ++ if ( sequence->picture.slices_size < size ) { ++ sequence->picture.slices_size = size+1024; ++ sequence->picture.slices = realloc( sequence->picture.slices, sequence->picture.slices_size ); ++ } ++ xine_fast_memcpy( sequence->picture.slices+sequence->picture.slices_pos, buf, len ); ++ sequence->picture.slices_pos += len; ++ if ( sequence->picture.slices_pos_top ) ++ sequence->picture.slices_count2++; ++ else ++ sequence->picture.slices_count++; ++} ++ ++ ++ ++static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) ++{ ++ sequence_t *sequence = (sequence_t*)&this_gen->sequence; ++ ++ if ( !sequence->have_header && buf[3]!=sequence_header_code ) { ++ lprintf( " ----------- no sequence header yet.\n" ); ++ return 0; ++ } ++ ++ if ( (buf[3] >= begin_slice_start_code) && (buf[3] <= end_slice_start_code) ) { ++ lprintf( " ----------- slice_start_code\n" ); ++ if ( sequence->picture.state==WANT_SLICE ) ++ copy_slice( sequence, buf, len ); ++ return 0; ++ } ++ else if ( sequence->picture.state==WANT_SLICE && sequence->picture.slices_count ) { ++ if ( !sequence->picture.slices_count2 ) { ++ sequence->picture.slices_pos_top = sequence->picture.slices_pos; ++ } ++ /* no more slices, decode */ ++ return 1; ++ } ++ ++ switch ( buf[3] ) { ++ case sequence_header_code: ++ lprintf( " ----------- sequence_header_code\n" ); ++ sequence_header( this_gen, buf+4, len-4 ); ++ break; ++ case extension_start_code: { ++ switch ( buf[4]>>4 ) { ++ case sequence_ext_sc: ++ lprintf( " ----------- sequence_extension_start_code\n" ); ++ sequence_extension( sequence, buf+4, len-4 ); ++ break; ++ case quant_matrix_ext_sc: ++ lprintf( " ----------- quant_matrix_extension_start_code\n" ); ++ quant_matrix_extension( sequence, buf+4, len-4 ); ++ break; ++ case picture_coding_ext_sc: ++ lprintf( " ----------- picture_coding_extension_start_code\n" ); ++ picture_coding_extension( sequence, buf+4, len-4 ); ++ break; ++ case sequence_display_ext_sc: ++ lprintf( " ----------- sequence_display_extension_start_code\n" ); ++ break; ++ } ++ break; ++ } ++ case user_data_start_code: ++ lprintf( " ----------- user_data_start_code\n" ); ++ break; ++ case group_start_code: ++ lprintf( " ----------- group_start_code\n" ); ++ break; ++ case picture_start_code: ++ lprintf( " ----------- picture_start_code\n" ); ++ picture_header( sequence, buf+4, len-4 ); ++ break; ++ case sequence_error_code: ++ lprintf( " ----------- sequence_error_code\n" ); ++ break; ++ case sequence_end_code: ++ lprintf( " ----------- sequence_end_code\n" ); ++ break; ++ } ++ return 0; ++} ++ ++ ++ ++static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) ++{ ++ sequence_t *seq = (sequence_t*)&vd->sequence; ++ picture_t *pic = (picture_t*)&seq->picture; ++ ++ pic->vdp_infos.slice_count = pic->slices_count; ++ pic->vdp_infos2.slice_count = pic->slices_count2; ++ ++ VdpStatus st; ++ if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) { ++ if ( vd->decoder!=VDP_INVALID_HANDLE ) { ++ accel->vdp_decoder_destroy( vd->decoder ); ++ vd->decoder = VDP_INVALID_HANDLE; ++ } ++ st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); ++ if ( st!=VDP_STATUS_OK ) ++ lprintf( "failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); ++ else { ++ vd->decoder_profile = seq->profile; ++ vd->decoder_width = seq->coded_width; ++ vd->decoder_height = seq->coded_height; ++ seq->vdp_runtime_nr = accel->vdp_runtime_nr; ++ } ++ } ++ ++ VdpBitstreamBuffer vbit; ++ vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; ++ vbit.bitstream = pic->slices; ++ vbit.bitstream_bytes = (pic->vdp_infos.picture_structure==PICTURE_FRAME)? pic->slices_pos : pic->slices_pos_top; ++ st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); ++ if ( st!=VDP_STATUS_OK ) ++ lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); ++ else { ++ lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", ++ pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->cur_pts ); ++ VdpPictureInfoMPEG1Or2 *info = &pic->vdp_infos; ++ lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->intra_dc_precision, info->frame_pred_frame_dct, info->concealment_motion_vectors, info->intra_vlc_format, info->alternate_scan, info->q_scale_type, info->top_field_first, info->full_pel_forward_vector, info->full_pel_backward_vector, info->f_code[0][0], info->f_code[0][1], info->f_code[1][0], info->f_code[1][1] ); ++ } ++ ++ if ( pic->vdp_infos.picture_structure != PICTURE_FRAME ) { ++ pic->vdp_infos2.backward_reference = VDP_INVALID_HANDLE; ++ pic->vdp_infos2.forward_reference = VDP_INVALID_HANDLE; ++ if ( pic->vdp_infos2.picture_coding_type==P_FRAME ) { ++ if ( pic->vdp_infos.picture_coding_type==I_FRAME ) ++ pic->vdp_infos2.forward_reference = accel->surface; ++ else ++ pic->vdp_infos2.forward_reference = pic->vdp_infos.forward_reference; ++ } ++ else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) { ++ pic->vdp_infos2.forward_reference = pic->vdp_infos.forward_reference; ++ pic->vdp_infos2.backward_reference = pic->vdp_infos.backward_reference; ++ } ++ vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; ++ vbit.bitstream = pic->slices+pic->slices_pos_top; ++ vbit.bitstream_bytes = pic->slices_pos-pic->slices_pos_top; ++ st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos2, 1, &vbit ); ++ if ( st!=VDP_STATUS_OK ) ++ lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); ++ else ++ lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", ++ pic->vdp_infos2.picture_coding_type, pic->vdp_infos2.slice_count, accel->surface, pic->vdp_infos2.forward_reference, pic->vdp_infos2.backward_reference, seq->cur_pts ); ++ } ++} ++ ++ ++ ++static void decode_picture( vdpau_mpeg12_decoder_t *vd ) ++{ ++ sequence_t *seq = (sequence_t*)&vd->sequence; ++ picture_t *pic = (picture_t*)&seq->picture; ++ vdpau_accel_t *ref_accel; ++ ++ pic->state = WANT_HEADER; ++ ++ if ( seq->profile == VDP_DECODER_PROFILE_MPEG1 ) ++ pic->vdp_infos.picture_structure=PICTURE_FRAME; ++ ++ if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && !pic->slices_count2 ) { ++ /* waiting second field */ ++ lprintf("********************* no slices_count2 **********************\n"); ++ return; ++ } ++ ++ if ( pic->vdp_infos.picture_coding_type==P_FRAME ) { ++ if ( seq->backward_ref ) { ++ ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; ++ pic->vdp_infos.forward_reference = ref_accel->surface; ++ } ++ else ++ return; ++ } ++ else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) { ++ if ( seq->forward_ref ) { ++ ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; ++ pic->vdp_infos.forward_reference = ref_accel->surface; ++ } ++ else ++ return; ++ if ( seq->backward_ref ) { ++ ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; ++ pic->vdp_infos.backward_reference = ref_accel->surface; ++ } ++ else ++ return; ++ } ++ ++ vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, ++ seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS|seq->chroma ); ++ vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; ++ if ( !seq->accel_vdpau ) ++ seq->accel_vdpau = accel; ++ ++ if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) { ++ seq->accel_vdpau = accel; ++ if ( seq->forward_ref ) ++ seq->forward_ref->free( seq->forward_ref ); ++ seq->forward_ref = NULL; ++ if ( seq->backward_ref ) ++ seq->backward_ref->free( seq->backward_ref ); ++ seq->backward_ref = NULL; ++ vd->decoder = VDP_INVALID_HANDLE; ++ } ++ ++ decode_render( vd, accel ); ++ ++#ifdef MAKE_DAT ++ if ( nframes==0 ) { ++ fwrite( &seq->coded_width, 1, sizeof(seq->coded_width), outfile ); ++ fwrite( &seq->coded_height, 1, sizeof(seq->coded_height), outfile ); ++ fwrite( &seq->ratio, 1, sizeof(seq->ratio), outfile ); ++ fwrite( &seq->profile, 1, sizeof(seq->profile), outfile ); ++ } ++ ++ if ( nframes++ < 25 ) { ++ fwrite( &pic->vdp_infos, 1, sizeof(pic->vdp_infos), outfile ); ++ fwrite( &pic->slices_pos, 1, sizeof(pic->slices_pos), outfile ); ++ fwrite( pic->slices, 1, pic->slices_pos, outfile ); ++ } ++#endif ++ ++ img->drawn = 0; ++ img->pts = seq->seq_pts; ++ seq->seq_pts = 0; /* reset */ ++ img->bad_frame = 0; ++ img->duration = seq->video_step; ++ ++ /* trying to deal with (french) buggy streams that randomly set bottom_field_first ++ while stream is top_field_first. So we assume that when top_field_first ++ is set one time, the stream _is_ top_field_first. */ ++ //printf("pic->vdp_infos.top_field_first = %d\n", pic->vdp_infos.top_field_first); ++ if ( pic->vdp_infos.top_field_first ) ++ seq->top_field_first = 1; ++ img->top_field_first = seq->top_field_first; ++ ++ /* progressive_frame is unreliable with most mpeg2 streams */ ++ if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME ) ++ img->progressive_frame = 0; ++ else ++ img->progressive_frame = pic->progressive_frame; ++ ++ if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { ++ if ( pic->vdp_infos.picture_coding_type==I_FRAME && !seq->backward_ref ) { ++ img->pts = 0; ++ img->draw( img, vd->stream ); ++ ++img->drawn; ++ } ++ if ( seq->forward_ref ) { ++ seq->forward_ref->drawn = 0; ++ seq->forward_ref->free( seq->forward_ref ); ++ } ++ seq->forward_ref = seq->backward_ref; ++ if ( seq->forward_ref && !seq->forward_ref->drawn ) { ++ seq->forward_ref->draw( seq->forward_ref, vd->stream ); ++ } ++ seq->backward_ref = img; ++ } ++ else { ++ img->draw( img, vd->stream ); ++ img->free( img ); ++ } ++} ++ ++ ++ ++/* ++ * This function receives a buffer of data from the demuxer layer and ++ * figures out how to handle it based on its header flags. ++ */ ++static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t *buf) ++{ ++ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; ++ sequence_t *seq = (sequence_t*)&this->sequence; ++ ++ /* preview buffers shall not be decoded and drawn -- use them only to supply stream information */ ++ if (buf->decoder_flags & BUF_FLAG_PREVIEW) ++ return; ++ ++ if ( !buf->size ) ++ return; ++ ++ seq->cur_pts = buf->pts; ++ ++ int size = seq->bufpos+buf->size; ++ if ( seq->bufsize < size ) { ++ seq->bufsize = size+1024; ++ seq->buf = realloc( seq->buf, seq->bufsize ); ++ } ++ xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); ++ seq->bufpos += buf->size; ++ ++ while ( seq->bufseek <= seq->bufpos-4 ) { ++ uint8_t *buffer = seq->buf+seq->bufseek; ++ if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { ++ if ( seq->start<0 ) { ++ seq->start = seq->bufseek; ++ } ++ else { ++ if ( parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ) ) { ++ decode_picture( this ); ++ parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ); ++ } ++ uint8_t *tmp = (uint8_t*)malloc(seq->bufsize); ++ xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek ); ++ seq->bufpos -= seq->bufseek; ++ seq->start = -1; ++ seq->bufseek = -1; ++ free( seq->buf ); ++ seq->buf = tmp; ++ } ++ } ++ ++seq->bufseek; ++ } ++ ++ /* still image detection -- don't wait for further data if buffer ends in sequence end code */ ++ if (seq->start >= 0 && seq->buf[seq->start + 3] == sequence_end_code) { ++ if (parse_code(this, seq->buf+seq->start, 4)) { ++ decode_picture(this); ++ parse_code(this, seq->buf+seq->start, 4); ++ } ++ seq->start = -1; ++ } ++} ++ ++/* ++ * This function is called when xine needs to flush the system. ++ */ ++static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { ++ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_mpeg12_flush\n" ); ++} ++ ++/* ++ * This function resets the video decoder. ++ */ ++static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { ++ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_mpeg12_reset\n" ); ++ reset_sequence( &this->sequence, 1 ); ++} ++ ++/* ++ * The decoder should forget any stored pts values here. ++ */ ++static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) { ++ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_mpeg12_discontinuity\n" ); ++ reset_sequence( &this->sequence, 0 ); ++} ++ ++/* ++ * This function frees the video decoder instance allocated to the decoder. ++ */ ++static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) { ++ ++ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; ++ ++ lprintf( "vdpau_mpeg12_dispose\n" ); ++ ++ if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) { ++ this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder ); ++ this->decoder = VDP_INVALID_HANDLE; ++ } ++ ++ free_sequence( &this->sequence ); ++ ++ this->stream->video_out->close( this->stream->video_out, this->stream ); ++ ++ free( this->sequence.picture.slices ); ++ free( this->sequence.buf ); ++ free( this_gen ); ++} ++ ++/* ++ * This function allocates, initializes, and returns a private video ++ * decoder structure. ++ */ ++static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { ++ ++ vdpau_mpeg12_decoder_t *this ; ++ ++ lprintf( "open_plugin\n" ); ++ ++ /* the videoout must be vdpau-capable to support this decoder */ ++ if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_MPEG12) ) ++ return NULL; ++ ++ /* now check if vdpau has free decoder resource */ ++ vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); ++ vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; ++ int runtime_nr = accel->vdp_runtime_nr; ++ img->free(img); ++ VdpDecoder decoder; ++ VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, 1920, 1080, 2, &decoder ); ++ if ( st!=VDP_STATUS_OK ) { ++ lprintf( "can't create vdpau decoder.\n" ); ++ return 1; ++ } ++ ++ accel->vdp_decoder_destroy( decoder ); ++ ++ this = (vdpau_mpeg12_decoder_t *) calloc(1, sizeof(vdpau_mpeg12_decoder_t)); ++ ++ this->video_decoder.decode_data = vdpau_mpeg12_decode_data; ++ this->video_decoder.flush = vdpau_mpeg12_flush; ++ this->video_decoder.reset = vdpau_mpeg12_reset; ++ this->video_decoder.discontinuity = vdpau_mpeg12_discontinuity; ++ this->video_decoder.dispose = vdpau_mpeg12_dispose; ++ ++ this->stream = stream; ++ this->class = (vdpau_mpeg12_class_t *) class_gen; ++ ++ this->sequence.bufsize = 1024; ++ this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); ++ this->sequence.forward_ref = 0; ++ this->sequence.backward_ref = 0; ++ this->sequence.vdp_runtime_nr = runtime_nr; ++ free_sequence( &this->sequence ); ++ this->sequence.ratio = 1; ++ ++ init_picture( &this->sequence.picture ); ++ ++ this->decoder = VDP_INVALID_HANDLE; ++ this->sequence.accel_vdpau = NULL; ++ ++ (stream->video_out->open)(stream->video_out, stream); ++ ++#ifdef MAKE_DAT ++ outfile = fopen( "/tmp/mpg.dat","w"); ++ nframes = 0; ++#endif ++ ++ return &this->video_decoder; ++} ++ ++/* ++ * This function returns a brief string that describes (usually with the ++ * decoder's most basic name) the video decoder plugin. ++ */ ++static char *get_identifier (video_decoder_class_t *this) { ++ return "vdpau_mpeg12"; ++} ++ ++/* ++ * This function returns a slightly longer string describing the video ++ * decoder plugin. ++ */ ++static char *get_description (video_decoder_class_t *this) { ++ return "vdpau_mpeg12: mpeg1/2 decoder plugin using VDPAU hardware decoding.\n" ++ "Must be used along with video_out_vdpau."; ++} ++ ++/* ++ * This function frees the video decoder class and any other memory that was ++ * allocated. ++ */ ++static void dispose_class (video_decoder_class_t *this) { ++ free (this); ++} ++ ++/* ++ * This function allocates a private video decoder class and initializes ++ * the class's member functions. ++ */ ++static void *init_plugin (xine_t *xine, void *data) { ++ ++ vdpau_mpeg12_class_t *this; ++ ++ this = (vdpau_mpeg12_class_t *) calloc(1, sizeof(vdpau_mpeg12_class_t)); ++ ++ this->decoder_class.open_plugin = open_plugin; ++ this->decoder_class.get_identifier = get_identifier; ++ this->decoder_class.get_description = get_description; ++ this->decoder_class.dispose = dispose_class; ++ ++ return this; ++} ++ ++/* ++ * This is a list of all of the internal xine video buffer types that ++ * this decoder is able to handle. Check src/xine-engine/buffer.h for a ++ * list of valid buffer types (and add a new one if the one you need does ++ * not exist). Terminate the list with a 0. ++ */ ++static const uint32_t video_types[] = { ++ BUF_VIDEO_MPEG, ++ 0 ++}; ++ ++/* ++ * This data structure combines the list of supported xine buffer types and ++ * the priority that the plugin should be given with respect to other ++ * plugins that handle the same buffer type. A plugin with priority (n+1) ++ * will be used instead of a plugin with priority (n). ++ */ ++static const decoder_info_t dec_info_video = { ++ video_types, /* supported types */ ++ 8 /* priority */ ++}; ++ ++/* ++ * The plugin catalog entry. This is the only information that this plugin ++ * will export to the public. ++ */ ++const plugin_info_t xine_plugin_info[] EXPORTED = { ++ /* { type, API, "name", version, special_info, init_function } */ ++ { PLUGIN_VIDEO_DECODER, 18, "vdpau_mpeg12", XINE_VERSION_CODE, &dec_info_video, init_plugin }, ++ { PLUGIN_NONE, 0, "", 0, NULL, NULL } ++}; +--- /dev/null ++++ xine-lib-1.1.19/src/libvdpau/Makefile.in +@@ -0,0 +1,914 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# @configure_input@ ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++@SET_MAKE@ ++ ++VPATH = @srcdir@ ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkglibexecdir = $(libexecdir)/@PACKAGE@ ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = @build@ ++host_triplet = @host@ ++DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ ++ $(top_srcdir)/misc/Makefile.common ++subdir = src/libvdpau ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/_xine.m4 $(top_srcdir)/m4/aa.m4 \ ++ $(top_srcdir)/m4/arts.m4 $(top_srcdir)/m4/attributes.m4 \ ++ $(top_srcdir)/m4/directx.m4 $(top_srcdir)/m4/dl.m4 \ ++ $(top_srcdir)/m4/dvdnav.m4 $(top_srcdir)/m4/gas.m4 \ ++ $(top_srcdir)/m4/getopt_long.m4 $(top_srcdir)/m4/gettext.m4 \ ++ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ ++ $(top_srcdir)/m4/ioctl_request.m4 $(top_srcdir)/m4/irixal.m4 \ ++ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lib-ld.m4 \ ++ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ ++ $(top_srcdir)/m4/libFLAC.m4 $(top_srcdir)/m4/libfame.m4 \ ++ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ ++ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ ++ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/misc.m4 \ ++ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/opengl.m4 \ ++ $(top_srcdir)/m4/optimizations.m4 $(top_srcdir)/m4/pkg.m4 \ ++ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ ++ $(top_srcdir)/m4/pthreads.m4 $(top_srcdir)/m4/symbol.m4 \ ++ $(top_srcdir)/m4/xv.m4 $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/include/configure.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; ++am__vpath_adj = case $$p in \ ++ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ ++ *) f=$$p;; \ ++ esac; ++am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; ++am__install_max = 40 ++am__nobase_strip_setup = \ ++ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` ++am__nobase_strip = \ ++ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" ++am__nobase_list = $(am__nobase_strip_setup); \ ++ for p in $$list; do echo "$$p $$p"; done | \ ++ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ ++ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ ++ if (++n[$$2] == $(am__install_max)) \ ++ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ ++ END { for (dir in files) print dir, files[dir] }' ++am__base_list = \ ++ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ ++ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' ++am__installdirs = "$(DESTDIR)$(xineplugdir)" ++LTLIBRARIES = $(xineplug_LTLIBRARIES) ++am__DEPENDENCIES_1 = ++xineplug_decode_vdpau_h264_la_DEPENDENCIES = $(XINE_LIB) \ ++ $(am__DEPENDENCIES_1) ++am_xineplug_decode_vdpau_h264_la_OBJECTS = \ ++ xineplug_decode_vdpau_h264_la-nal.lo \ ++ xineplug_decode_vdpau_h264_la-dpb.lo \ ++ xineplug_decode_vdpau_h264_la-h264_parser.lo \ ++ xineplug_decode_vdpau_h264_la-vdpau_h264.lo ++xineplug_decode_vdpau_h264_la_OBJECTS = \ ++ $(am_xineplug_decode_vdpau_h264_la_OBJECTS) ++xineplug_decode_vdpau_h264_la_LINK = $(LIBTOOL) --tag=CC \ ++ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ ++ $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) \ ++ $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++@HAVE_VDPAU_TRUE@am_xineplug_decode_vdpau_h264_la_rpath = -rpath \ ++@HAVE_VDPAU_TRUE@ $(xineplugdir) ++xineplug_decode_vdpau_mpeg12_la_DEPENDENCIES = $(XINE_LIB) \ ++ $(am__DEPENDENCIES_1) ++am_xineplug_decode_vdpau_mpeg12_la_OBJECTS = \ ++ xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.lo ++xineplug_decode_vdpau_mpeg12_la_OBJECTS = \ ++ $(am_xineplug_decode_vdpau_mpeg12_la_OBJECTS) ++xineplug_decode_vdpau_mpeg12_la_LINK = $(LIBTOOL) --tag=CC \ ++ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ ++ $(xineplug_decode_vdpau_mpeg12_la_CFLAGS) $(CFLAGS) \ ++ $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++@HAVE_VDPAU_TRUE@am_xineplug_decode_vdpau_mpeg12_la_rpath = -rpath \ ++@HAVE_VDPAU_TRUE@ $(xineplugdir) ++xineplug_decode_vdpau_vc1_la_DEPENDENCIES = $(XINE_LIB) \ ++ $(am__DEPENDENCIES_1) ++am_xineplug_decode_vdpau_vc1_la_OBJECTS = \ ++ xineplug_decode_vdpau_vc1_la-vdpau_vc1.lo ++xineplug_decode_vdpau_vc1_la_OBJECTS = \ ++ $(am_xineplug_decode_vdpau_vc1_la_OBJECTS) ++xineplug_decode_vdpau_vc1_la_LINK = $(LIBTOOL) --tag=CC \ ++ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ ++ $(xineplug_decode_vdpau_vc1_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ ++ $(LDFLAGS) -o $@ ++@HAVE_VDPAU_TRUE@am_xineplug_decode_vdpau_vc1_la_rpath = -rpath \ ++@HAVE_VDPAU_TRUE@ $(xineplugdir) ++DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include ++depcomp = $(SHELL) $(top_srcdir)/depcomp ++am__depfiles_maybe = depfiles ++am__mv = mv -f ++COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ ++ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ ++ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++CCLD = $(CC) ++LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ ++ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ ++ $(LDFLAGS) -o $@ ++SOURCES = $(xineplug_decode_vdpau_h264_la_SOURCES) \ ++ $(xineplug_decode_vdpau_mpeg12_la_SOURCES) \ ++ $(xineplug_decode_vdpau_vc1_la_SOURCES) ++DIST_SOURCES = $(xineplug_decode_vdpau_h264_la_SOURCES) \ ++ $(xineplug_decode_vdpau_mpeg12_la_SOURCES) \ ++ $(xineplug_decode_vdpau_vc1_la_SOURCES) ++ETAGS = etags ++CTAGS = ctags ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++AAINFO = @AAINFO@ ++AALIB_CFLAGS = @AALIB_CFLAGS@ ++AALIB_CONFIG = @AALIB_CONFIG@ ++AALIB_LIBS = @AALIB_LIBS@ ++ACLOCAL = @ACLOCAL@ ++ACLOCAL_DIR = @ACLOCAL_DIR@ ++ALSA_CFLAGS = @ALSA_CFLAGS@ ++ALSA_LIBS = @ALSA_LIBS@ ++AMTAR = @AMTAR@ ++AR = @AR@ ++ARTS_CFLAGS = @ARTS_CFLAGS@ ++ARTS_CONFIG = @ARTS_CONFIG@ ++ARTS_LIBS = @ARTS_LIBS@ ++AS = @AS@ ++ASFLAGS = @ASFLAGS@ ++AUTOCONF = @AUTOCONF@ ++AUTOHEADER = @AUTOHEADER@ ++AUTOMAKE = @AUTOMAKE@ ++AWK = @AWK@ ++CACA_CFLAGS = @CACA_CFLAGS@ ++CACA_LIBS = @CACA_LIBS@ ++CC = @CC@ ++CCAS = @CCAS@ ++CCASDEPMODE = @CCASDEPMODE@ ++CCASFLAGS = @CCASFLAGS@ ++CCDEPMODE = @CCDEPMODE@ ++CFLAGS = @CFLAGS@ ++CPP = @CPP@ ++CPPFLAGS = @CPPFLAGS@ ++CYGPATH_W = @CYGPATH_W@ ++DEBUG_CFLAGS = @DEBUG_CFLAGS@ ++DEFS = @DEFS@ ++DEPCOMP = @DEPCOMP@ ++DEPDIR = @DEPDIR@ ++DEPMOD = @DEPMOD@ ++DIRECTFB_CFLAGS = @DIRECTFB_CFLAGS@ ++DIRECTFB_LIBS = @DIRECTFB_LIBS@ ++DIRECTX_AUDIO_LIBS = @DIRECTX_AUDIO_LIBS@ ++DIRECTX_CPPFLAGS = @DIRECTX_CPPFLAGS@ ++DIRECTX_VIDEO_LIBS = @DIRECTX_VIDEO_LIBS@ ++DLLTOOL = @DLLTOOL@ ++DSYMUTIL = @DSYMUTIL@ ++DUMPBIN = @DUMPBIN@ ++DVDNAV_CFLAGS = @DVDNAV_CFLAGS@ ++DVDNAV_CONFIG = @DVDNAV_CONFIG@ ++DVDNAV_LIBS = @DVDNAV_LIBS@ ++DYNAMIC_LD_LIBS = @DYNAMIC_LD_LIBS@ ++ECHO_C = @ECHO_C@ ++ECHO_N = @ECHO_N@ ++ECHO_T = @ECHO_T@ ++EGREP = @EGREP@ ++ESD_CFLAGS = @ESD_CFLAGS@ ++ESD_LIBS = @ESD_LIBS@ ++EXEEXT = @EXEEXT@ ++EXTRA_X_CFLAGS = @EXTRA_X_CFLAGS@ ++EXTRA_X_LIBS = @EXTRA_X_LIBS@ ++FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ ++FFMPEG_LIBS = @FFMPEG_LIBS@ ++FFMPEG_POSTPROC_CFLAGS = @FFMPEG_POSTPROC_CFLAGS@ ++FFMPEG_POSTPROC_LIBS = @FFMPEG_POSTPROC_LIBS@ ++FFMPEG_UTIL_CFLAGS = @FFMPEG_UTIL_CFLAGS@ ++FFMPEG_UTIL_LIBS = @FFMPEG_UTIL_LIBS@ ++FGREP = @FGREP@ ++FIG2DEV = @FIG2DEV@ ++FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ ++FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ ++FT2_CFLAGS = @FT2_CFLAGS@ ++FT2_LIBS = @FT2_LIBS@ ++FUSIONSOUND_CFLAGS = @FUSIONSOUND_CFLAGS@ ++FUSIONSOUND_LIBS = @FUSIONSOUND_LIBS@ ++GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ ++GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ ++GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ ++GLU_LIBS = @GLU_LIBS@ ++GMSGFMT = @GMSGFMT@ ++GMSGFMT_015 = @GMSGFMT_015@ ++GNOME_VFS_CFLAGS = @GNOME_VFS_CFLAGS@ ++GNOME_VFS_LIBS = @GNOME_VFS_LIBS@ ++GOOM_LIBS = @GOOM_LIBS@ ++GRAPHICSMAGICKWAND_CFLAGS = @GRAPHICSMAGICKWAND_CFLAGS@ ++GRAPHICSMAGICKWAND_LIBS = @GRAPHICSMAGICKWAND_LIBS@ ++GRAPHICSMAGICK_CFLAGS = @GRAPHICSMAGICK_CFLAGS@ ++GRAPHICSMAGICK_LIBS = @GRAPHICSMAGICK_LIBS@ ++GREP = @GREP@ ++HAVE_BSDI_CDROM = @HAVE_BSDI_CDROM@ ++HAVE_DARWIN_CDROM = @HAVE_DARWIN_CDROM@ ++HAVE_FREEBSD_CDROM = @HAVE_FREEBSD_CDROM@ ++HAVE_LINUX_CDROM = @HAVE_LINUX_CDROM@ ++HAVE_SOLARIS_CDROM = @HAVE_SOLARIS_CDROM@ ++HAVE_WIN32_CDROM = @HAVE_WIN32_CDROM@ ++IMPURE_TEXT_LDFLAGS = @IMPURE_TEXT_LDFLAGS@ ++INCLUDES = @INCLUDES@ ++INSTALL = @INSTALL@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ ++INTLLIBS = @INTLLIBS@ ++INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ ++IRIXAL_CFLAGS = @IRIXAL_CFLAGS@ ++IRIXAL_LIBS = @IRIXAL_LIBS@ ++IRIXAL_STATIC_LIB = @IRIXAL_STATIC_LIB@ ++JACK_CFLAGS = @JACK_CFLAGS@ ++JACK_LIBS = @JACK_LIBS@ ++KSTAT_LIBS = @KSTAT_LIBS@ ++LD = @LD@ ++LDFLAGS = @LDFLAGS@ ++LDFLAGS_NOUNDEFINED = @LDFLAGS_NOUNDEFINED@ ++LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@ ++LIBCDIO_LIBS = @LIBCDIO_LIBS@ ++LIBDTS_CFLAGS = @LIBDTS_CFLAGS@ ++LIBDTS_LIBS = @LIBDTS_LIBS@ ++LIBFAME_CFLAGS = @LIBFAME_CFLAGS@ ++LIBFAME_CONFIG = @LIBFAME_CONFIG@ ++LIBFAME_LIBS = @LIBFAME_LIBS@ ++LIBFFMPEG_CPPFLAGS = @LIBFFMPEG_CPPFLAGS@ ++LIBFLAC_CFLAGS = @LIBFLAC_CFLAGS@ ++LIBFLAC_LIBS = @LIBFLAC_LIBS@ ++LIBICONV = @LIBICONV@ ++LIBINTL = @LIBINTL@ ++LIBISO9660_LIBS = @LIBISO9660_LIBS@ ++LIBMAD_CFLAGS = @LIBMAD_CFLAGS@ ++LIBMAD_LIBS = @LIBMAD_LIBS@ ++LIBMODPLUG_CFLAGS = @LIBMODPLUG_CFLAGS@ ++LIBMODPLUG_LIBS = @LIBMODPLUG_LIBS@ ++LIBMPEG2_CFLAGS = @LIBMPEG2_CFLAGS@ ++LIBNAME = @LIBNAME@ ++LIBOBJS = @LIBOBJS@ ++LIBS = @LIBS@ ++LIBSMBCLIENT_LIBS = @LIBSMBCLIENT_LIBS@ ++LIBSTK_CFLAGS = @LIBSTK_CFLAGS@ ++LIBSTK_LIBS = @LIBSTK_LIBS@ ++LIBTOOL = @LIBTOOL@ ++LIBTOOL_DEPS = @LIBTOOL_DEPS@ ++LIBTOOL_DESTDIR_DEFAULT = @LIBTOOL_DESTDIR_DEFAULT@ ++LIBVCDINFO_CFLAGS = @LIBVCDINFO_CFLAGS@ ++LIBVCDINFO_LIBS = @LIBVCDINFO_LIBS@ ++LIBVCD_CFLAGS = @LIBVCD_CFLAGS@ ++LIBVCD_LIBS = @LIBVCD_LIBS@ ++LIBVCD_SYSDEP = @LIBVCD_SYSDEP@ ++LINUX_CDROM_TIMEOUT = @LINUX_CDROM_TIMEOUT@ ++LINUX_INCLUDE = @LINUX_INCLUDE@ ++LIPO = @LIPO@ ++LN_S = @LN_S@ ++LTLIBICONV = @LTLIBICONV@ ++LTLIBINTL = @LTLIBINTL@ ++LTLIBOBJS = @LTLIBOBJS@ ++MAGICKWAND_CFLAGS = @MAGICKWAND_CFLAGS@ ++MAGICKWAND_LIBS = @MAGICKWAND_LIBS@ ++MAKEINFO = @MAKEINFO@ ++MKDIR_P = @MKDIR_P@ ++MKINSTALLDIRS = @MKINSTALLDIRS@ ++MKNOD = @MKNOD@ ++MLIB_CFLAGS = @MLIB_CFLAGS@ ++MLIB_LIBS = @MLIB_LIBS@ ++MNG_LIBS = @MNG_LIBS@ ++MSGFMT = @MSGFMT@ ++MSGFMT_015 = @MSGFMT_015@ ++MSGMERGE = @MSGMERGE@ ++NET_LIBS = @NET_LIBS@ ++NM = @NM@ ++NMEDIT = @NMEDIT@ ++OBJC = @OBJC@ ++OBJCDEPMODE = @OBJCDEPMODE@ ++OBJCFLAGS = @OBJCFLAGS@ ++OBJDUMP = @OBJDUMP@ ++OBJEXT = @OBJEXT@ ++OPENGL_CFLAGS = @OPENGL_CFLAGS@ ++OPENGL_LIBS = @OPENGL_LIBS@ ++OTOOL = @OTOOL@ ++OTOOL64 = @OTOOL64@ ++PACKAGE = @PACKAGE@ ++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_STRING = @PACKAGE_STRING@ ++PACKAGE_TARNAME = @PACKAGE_TARNAME@ ++PACKAGE_URL = @PACKAGE_URL@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++PASS1_CFLAGS = @PASS1_CFLAGS@ ++PASS2_CFLAGS = @PASS2_CFLAGS@ ++PATH_SEPARATOR = @PATH_SEPARATOR@ ++PERL = @PERL@ ++PKG_CONFIG = @PKG_CONFIG@ ++POSUB = @POSUB@ ++PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ ++PTHREAD_LIBS = @PTHREAD_LIBS@ ++PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ ++PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ ++RANLIB = @RANLIB@ ++RT_LIBS = @RT_LIBS@ ++SDL_CFLAGS = @SDL_CFLAGS@ ++SDL_LIBS = @SDL_LIBS@ ++SED = @SED@ ++SET_MAKE = @SET_MAKE@ ++SGMLTOOLS = @SGMLTOOLS@ ++SHELL = @SHELL@ ++SNDIO_CFLAGS = @SNDIO_CFLAGS@ ++SNDIO_LIBS = @SNDIO_LIBS@ ++SPEC_VERSION = @SPEC_VERSION@ ++SPEEX_CFLAGS = @SPEEX_CFLAGS@ ++SPEEX_LIBS = @SPEEX_LIBS@ ++STATIC = @STATIC@ ++STRINGS = @STRINGS@ ++STRIP = @STRIP@ ++SUNDGA_CFLAGS = @SUNDGA_CFLAGS@ ++SUNDGA_LIBS = @SUNDGA_LIBS@ ++TAR_NAME = @TAR_NAME@ ++THEORA_CFLAGS = @THEORA_CFLAGS@ ++THEORA_LIBS = @THEORA_LIBS@ ++USE_NLS = @USE_NLS@ ++V4L2_CFLAGS = @V4L2_CFLAGS@ ++V4L2_LIBS = @V4L2_LIBS@ ++VERSION = @VERSION@ ++VISIBILITY_FLAG = @VISIBILITY_FLAG@ ++VORBIS_CFLAGS = @VORBIS_CFLAGS@ ++VORBIS_LIBS = @VORBIS_LIBS@ ++W32_NO_OPTIMIZE = @W32_NO_OPTIMIZE@ ++WAND_CFLAGS = @WAND_CFLAGS@ ++WAND_LIBS = @WAND_LIBS@ ++WAVPACK_CFLAGS = @WAVPACK_CFLAGS@ ++WAVPACK_LIBS = @WAVPACK_LIBS@ ++WIN32_CPPFLAGS = @WIN32_CPPFLAGS@ ++XCBSHM_CFLAGS = @XCBSHM_CFLAGS@ ++XCBSHM_LIBS = @XCBSHM_LIBS@ ++XCBXV_CFLAGS = @XCBXV_CFLAGS@ ++XCBXV_LIBS = @XCBXV_LIBS@ ++XCB_CFLAGS = @XCB_CFLAGS@ ++XCB_LIBS = @XCB_LIBS@ ++XGETTEXT = @XGETTEXT@ ++XGETTEXT_015 = @XGETTEXT_015@ ++XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ ++XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ ++XINERAMA_LIBS = @XINERAMA_LIBS@ ++XINE_ACFLAGS = @XINE_ACFLAGS@ ++XINE_BIN_AGE = @XINE_BIN_AGE@ ++XINE_BUILD_CC = @XINE_BUILD_CC@ ++XINE_BUILD_DATE = @XINE_BUILD_DATE@ ++XINE_BUILD_OS = @XINE_BUILD_OS@ ++XINE_DATADIR = @XINE_DATADIR@ ++XINE_FONTDIR = @XINE_FONTDIR@ ++XINE_IFACE_AGE = @XINE_IFACE_AGE@ ++XINE_LOCALEDIR = @XINE_LOCALEDIR@ ++XINE_LT_AGE = @XINE_LT_AGE@ ++XINE_LT_CURRENT = @XINE_LT_CURRENT@ ++XINE_LT_REVISION = @XINE_LT_REVISION@ ++XINE_MAJOR = @XINE_MAJOR@ ++XINE_MINOR = @XINE_MINOR@ ++XINE_PATCH = @XINE_PATCH@ ++XINE_PKGCONFIG_DIR = @XINE_PKGCONFIG_DIR@ ++XINE_PLUGINDIR = @XINE_PLUGINDIR@ ++XINE_SCRIPTPATH = @XINE_SCRIPTPATH@ ++XINE_SERIES = @XINE_SERIES@ ++XINE_SUB = @XINE_SUB@ ++XMKMF = @XMKMF@ ++XVMC_LIBS = @XVMC_LIBS@ ++XV_CFLAGS = @XV_CFLAGS@ ++XV_LIBS = @XV_LIBS@ ++XXMC_LIBS = @XXMC_LIBS@ ++X_CFLAGS = @X_CFLAGS@ ++X_EXTRA_LIBS = @X_EXTRA_LIBS@ ++X_LIBS = @X_LIBS@ ++X_PRE_LIBS = @X_PRE_LIBS@ ++ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ++ZLIB_LIBS = @ZLIB_LIBS@ ++abs_builddir = @abs_builddir@ ++abs_srcdir = @abs_srcdir@ ++abs_top_builddir = @abs_top_builddir@ ++abs_top_srcdir = @abs_top_srcdir@ ++ac_ct_CC = @ac_ct_CC@ ++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ++ac_ct_OBJC = @ac_ct_OBJC@ ++am__include = @am__include@ ++am__leading_dot = @am__leading_dot@ ++am__quote = @am__quote@ ++am__tar = @am__tar@ ++am__untar = @am__untar@ ++bindir = @bindir@ ++build = @build@ ++build_alias = @build_alias@ ++build_cpu = @build_cpu@ ++build_os = @build_os@ ++build_vendor = @build_vendor@ ++builddir = @builddir@ ++datadir = @datadir@ ++datarootdir = @datarootdir@ ++docdir = @docdir@ ++dvidir = @dvidir@ ++exec_prefix = @exec_prefix@ ++host = @host@ ++host_alias = @host_alias@ ++host_cpu = @host_cpu@ ++host_os = @host_os@ ++host_vendor = @host_vendor@ ++htmldir = @htmldir@ ++includedir = @includedir@ ++infodir = @infodir@ ++install_sh = @install_sh@ ++libdir = @libdir@ ++libexecdir = @libexecdir@ ++localedir = @localedir@ ++localstatedir = @localstatedir@ ++lt_ECHO = @lt_ECHO@ ++mandir = @mandir@ ++mkdir_p = @mkdir_p@ ++oldincludedir = @oldincludedir@ ++pdfdir = @pdfdir@ ++pkgconfigdir = @pkgconfigdir@ ++prefix = @prefix@ ++program_transform_name = @program_transform_name@ ++psdir = @psdir@ ++sbindir = @sbindir@ ++sharedstatedir = @sharedstatedir@ ++srcdir = @srcdir@ ++sysconfdir = @sysconfdir@ ++target_alias = @target_alias@ ++top_build_prefix = @top_build_prefix@ ++top_builddir = @top_builddir@ ++top_srcdir = @top_srcdir@ ++w32_path = @w32_path@ ++xinedatadir = @xinedatadir@ ++xinelibdir = @xinelibdir@ ++XINE_LIB = $(top_builddir)/src/xine-engine/libxine.la ++xineincludedir = $(includedir)/xine ++xineplugdir = $(XINE_PLUGINDIR) ++xineplug_ldflags = $(LDFLAGS_NOUNDEFINED) -avoid-version -module ++xinepostdir = $(XINE_PLUGINDIR)/post ++vidixdir = $(XINE_PLUGINDIR)/vidix ++AM_CFLAGS = $(VISIBILITY_FLAG) ++AM_LDFLAGS = $(xineplug_ldflags) ++@HAVE_VDPAU_TRUE@vdpau_h264_module = xineplug_decode_vdpau_h264.la ++@HAVE_VDPAU_TRUE@VDPAU_CFLAGS = -D_ISOC99_SOURCE ++@HAVE_VDPAU_TRUE@vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la ++@HAVE_VDPAU_TRUE@vdpau_vc1_module = xineplug_decode_vdpau_vc1.la ++xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) $(vdpau_vc1_module) ++xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c ++xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) ++xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) -lm ++xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c ++xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS) ++xineplug_decode_vdpau_mpeg12_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) ++xineplug_decode_vdpau_vc1_la_SOURCES = vdpau_vc1.c ++xineplug_decode_vdpau_vc1_la_CFLAGS = $(AM_CFLAGS) ++xineplug_decode_vdpau_vc1_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) ++all: all-am ++ ++.SUFFIXES: ++.SUFFIXES: .c .lo .o .obj ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/misc/Makefile.common $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libvdpau/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --gnu src/libvdpau/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++install-xineplugLTLIBRARIES: $(xineplug_LTLIBRARIES) ++ @$(NORMAL_INSTALL) ++ test -z "$(xineplugdir)" || $(MKDIR_P) "$(DESTDIR)$(xineplugdir)" ++ @list='$(xineplug_LTLIBRARIES)'; test -n "$(xineplugdir)" || list=; \ ++ list2=; for p in $$list; do \ ++ if test -f $$p; then \ ++ list2="$$list2 $$p"; \ ++ else :; fi; \ ++ done; \ ++ test -z "$$list2" || { \ ++ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(xineplugdir)'"; \ ++ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(xineplugdir)"; \ ++ } ++ ++uninstall-xineplugLTLIBRARIES: ++ @$(NORMAL_UNINSTALL) ++ @list='$(xineplug_LTLIBRARIES)'; test -n "$(xineplugdir)" || list=; \ ++ for p in $$list; do \ ++ $(am__strip_dir) \ ++ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(xineplugdir)/$$f'"; \ ++ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(xineplugdir)/$$f"; \ ++ done ++ ++clean-xineplugLTLIBRARIES: ++ -test -z "$(xineplug_LTLIBRARIES)" || rm -f $(xineplug_LTLIBRARIES) ++ @list='$(xineplug_LTLIBRARIES)'; for p in $$list; do \ ++ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ ++ test "$$dir" != "$$p" || dir=.; \ ++ echo "rm -f \"$${dir}/so_locations\""; \ ++ rm -f "$${dir}/so_locations"; \ ++ done ++xineplug_decode_vdpau_h264.la: $(xineplug_decode_vdpau_h264_la_OBJECTS) $(xineplug_decode_vdpau_h264_la_DEPENDENCIES) ++ $(xineplug_decode_vdpau_h264_la_LINK) $(am_xineplug_decode_vdpau_h264_la_rpath) $(xineplug_decode_vdpau_h264_la_OBJECTS) $(xineplug_decode_vdpau_h264_la_LIBADD) $(LIBS) ++xineplug_decode_vdpau_mpeg12.la: $(xineplug_decode_vdpau_mpeg12_la_OBJECTS) $(xineplug_decode_vdpau_mpeg12_la_DEPENDENCIES) ++ $(xineplug_decode_vdpau_mpeg12_la_LINK) $(am_xineplug_decode_vdpau_mpeg12_la_rpath) $(xineplug_decode_vdpau_mpeg12_la_OBJECTS) $(xineplug_decode_vdpau_mpeg12_la_LIBADD) $(LIBS) ++xineplug_decode_vdpau_vc1.la: $(xineplug_decode_vdpau_vc1_la_OBJECTS) $(xineplug_decode_vdpau_vc1_la_DEPENDENCIES) ++ $(xineplug_decode_vdpau_vc1_la_LINK) $(am_xineplug_decode_vdpau_vc1_la_rpath) $(xineplug_decode_vdpau_vc1_la_OBJECTS) $(xineplug_decode_vdpau_vc1_la_LIBADD) $(LIBS) ++ ++mostlyclean-compile: ++ -rm -f *.$(OBJEXT) ++ ++distclean-compile: ++ -rm -f *.tab.c ++ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_decode_vdpau_h264_la-dpb.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_decode_vdpau_h264_la-h264_parser.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_decode_vdpau_h264_la-nal.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_decode_vdpau_h264_la-vdpau_h264.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_decode_vdpau_vc1_la-vdpau_vc1.Plo@am__quote@ ++ ++.c.o: ++@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(COMPILE) -c $< ++ ++.c.obj: ++@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` ++ ++.c.lo: ++@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< ++ ++xineplug_decode_vdpau_h264_la-nal.lo: nal.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -MT xineplug_decode_vdpau_h264_la-nal.lo -MD -MP -MF $(DEPDIR)/xineplug_decode_vdpau_h264_la-nal.Tpo -c -o xineplug_decode_vdpau_h264_la-nal.lo `test -f 'nal.c' || echo '$(srcdir)/'`nal.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_decode_vdpau_h264_la-nal.Tpo $(DEPDIR)/xineplug_decode_vdpau_h264_la-nal.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nal.c' object='xineplug_decode_vdpau_h264_la-nal.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -c -o xineplug_decode_vdpau_h264_la-nal.lo `test -f 'nal.c' || echo '$(srcdir)/'`nal.c ++ ++xineplug_decode_vdpau_h264_la-dpb.lo: dpb.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -MT xineplug_decode_vdpau_h264_la-dpb.lo -MD -MP -MF $(DEPDIR)/xineplug_decode_vdpau_h264_la-dpb.Tpo -c -o xineplug_decode_vdpau_h264_la-dpb.lo `test -f 'dpb.c' || echo '$(srcdir)/'`dpb.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_decode_vdpau_h264_la-dpb.Tpo $(DEPDIR)/xineplug_decode_vdpau_h264_la-dpb.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dpb.c' object='xineplug_decode_vdpau_h264_la-dpb.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -c -o xineplug_decode_vdpau_h264_la-dpb.lo `test -f 'dpb.c' || echo '$(srcdir)/'`dpb.c ++ ++xineplug_decode_vdpau_h264_la-h264_parser.lo: h264_parser.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -MT xineplug_decode_vdpau_h264_la-h264_parser.lo -MD -MP -MF $(DEPDIR)/xineplug_decode_vdpau_h264_la-h264_parser.Tpo -c -o xineplug_decode_vdpau_h264_la-h264_parser.lo `test -f 'h264_parser.c' || echo '$(srcdir)/'`h264_parser.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_decode_vdpau_h264_la-h264_parser.Tpo $(DEPDIR)/xineplug_decode_vdpau_h264_la-h264_parser.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='h264_parser.c' object='xineplug_decode_vdpau_h264_la-h264_parser.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -c -o xineplug_decode_vdpau_h264_la-h264_parser.lo `test -f 'h264_parser.c' || echo '$(srcdir)/'`h264_parser.c ++ ++xineplug_decode_vdpau_h264_la-vdpau_h264.lo: vdpau_h264.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -MT xineplug_decode_vdpau_h264_la-vdpau_h264.lo -MD -MP -MF $(DEPDIR)/xineplug_decode_vdpau_h264_la-vdpau_h264.Tpo -c -o xineplug_decode_vdpau_h264_la-vdpau_h264.lo `test -f 'vdpau_h264.c' || echo '$(srcdir)/'`vdpau_h264.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_decode_vdpau_h264_la-vdpau_h264.Tpo $(DEPDIR)/xineplug_decode_vdpau_h264_la-vdpau_h264.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vdpau_h264.c' object='xineplug_decode_vdpau_h264_la-vdpau_h264.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_h264_la_CFLAGS) $(CFLAGS) -c -o xineplug_decode_vdpau_h264_la-vdpau_h264.lo `test -f 'vdpau_h264.c' || echo '$(srcdir)/'`vdpau_h264.c ++ ++xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.lo: vdpau_mpeg12.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_mpeg12_la_CFLAGS) $(CFLAGS) -MT xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.lo -MD -MP -MF $(DEPDIR)/xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.Tpo -c -o xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.lo `test -f 'vdpau_mpeg12.c' || echo '$(srcdir)/'`vdpau_mpeg12.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.Tpo $(DEPDIR)/xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vdpau_mpeg12.c' object='xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_mpeg12_la_CFLAGS) $(CFLAGS) -c -o xineplug_decode_vdpau_mpeg12_la-vdpau_mpeg12.lo `test -f 'vdpau_mpeg12.c' || echo '$(srcdir)/'`vdpau_mpeg12.c ++ ++xineplug_decode_vdpau_vc1_la-vdpau_vc1.lo: vdpau_vc1.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_vc1_la_CFLAGS) $(CFLAGS) -MT xineplug_decode_vdpau_vc1_la-vdpau_vc1.lo -MD -MP -MF $(DEPDIR)/xineplug_decode_vdpau_vc1_la-vdpau_vc1.Tpo -c -o xineplug_decode_vdpau_vc1_la-vdpau_vc1.lo `test -f 'vdpau_vc1.c' || echo '$(srcdir)/'`vdpau_vc1.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_decode_vdpau_vc1_la-vdpau_vc1.Tpo $(DEPDIR)/xineplug_decode_vdpau_vc1_la-vdpau_vc1.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vdpau_vc1.c' object='xineplug_decode_vdpau_vc1_la-vdpau_vc1.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_decode_vdpau_vc1_la_CFLAGS) $(CFLAGS) -c -o xineplug_decode_vdpau_vc1_la-vdpau_vc1.lo `test -f 'vdpau_vc1.c' || echo '$(srcdir)/'`vdpau_vc1.c ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++ ++ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) ++ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | \ ++ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in files) print i; }; }'`; \ ++ mkid -fID $$unique ++tags: TAGS ++ ++TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ ++ $(TAGS_FILES) $(LISP) ++ set x; \ ++ here=`pwd`; \ ++ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | \ ++ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in files) print i; }; }'`; \ ++ shift; \ ++ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ ++ test -n "$$unique" || unique=$$empty_fix; \ ++ if test $$# -gt 0; then \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ "$$@" $$unique; \ ++ else \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ $$unique; \ ++ fi; \ ++ fi ++ctags: CTAGS ++CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ ++ $(TAGS_FILES) $(LISP) ++ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | \ ++ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in files) print i; }; }'`; \ ++ test -z "$(CTAGS_ARGS)$$unique" \ ++ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ ++ $$unique ++ ++GTAGS: ++ here=`$(am__cd) $(top_builddir) && pwd` \ ++ && $(am__cd) $(top_srcdir) \ ++ && gtags -i $(GTAGS_ARGS) "$$here" ++ ++distclean-tags: ++ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile $(LTLIBRARIES) ++installdirs: ++ for dir in "$(DESTDIR)$(xineplugdir)"; do \ ++ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ ++ done ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-xineplugLTLIBRARIES \ ++ mostlyclean-am ++ ++distclean: distclean-am ++ -rm -rf ./$(DEPDIR) ++ -rm -f Makefile ++distclean-am: clean-am distclean-compile distclean-generic \ ++ distclean-tags ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: install-xineplugLTLIBRARIES ++ @$(NORMAL_INSTALL) ++ $(MAKE) $(AM_MAKEFLAGS) install-data-hook ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -rf ./$(DEPDIR) ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-compile mostlyclean-generic \ ++ mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: uninstall-xineplugLTLIBRARIES ++ @$(NORMAL_INSTALL) ++ $(MAKE) $(AM_MAKEFLAGS) uninstall-hook ++.MAKE: install-am install-data-am install-strip uninstall-am ++ ++.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ ++ clean-libtool clean-xineplugLTLIBRARIES ctags distclean \ ++ distclean-compile distclean-generic distclean-libtool \ ++ distclean-tags distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am \ ++ install-data-hook install-dvi install-dvi-am install-exec \ ++ install-exec-am install-html install-html-am install-info \ ++ install-info-am install-man install-pdf install-pdf-am \ ++ install-ps install-ps-am install-strip \ ++ install-xineplugLTLIBRARIES installcheck installcheck-am \ ++ installdirs maintainer-clean maintainer-clean-generic \ ++ mostlyclean mostlyclean-compile mostlyclean-generic \ ++ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ ++ uninstall-am uninstall-hook uninstall-xineplugLTLIBRARIES ++ ++ ++$(XINE_LIB): ++ @cd $(top_builddir)/src/xine-engine && $(MAKE) ++ ++install-data-hook: ++ @if test $$MAKELEVEL -le 4 ; then \ ++ if test -x "$(top_srcdir)/post-install.sh" ; then \ ++ $(top_srcdir)/post-install.sh ; \ ++ fi; \ ++ fi; \ ++ if test -x /usr/bin/chcon -a "`id -u`" -eq 0; then \ ++ list='$(xineplug_LTLIBRARIES)'; \ ++ for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xineplugdir)/$$p"; \ ++ chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xineplugdir)/$$p || :; \ ++ done; \ ++ list='$(xinepost_LTLIBRARIES)'; \ ++ for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xinepostdir)/$$p"; \ ++ chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xinepostdir)/$$p || :; \ ++ done; \ ++ fi ++ ++pass1: ++ @$(MAKE) MULTIPASS_CFLAGS="$(PASS1_CFLAGS)" ++ ++pass2: ++ @$(MAKE) MULTIPASS_CFLAGS="$(PASS2_CFLAGS)" ++ ++debug: ++ @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" ++ ++install-debug: debug ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ @list='$(SUBDIRS)'; for subdir in $$list; do \ ++ (cd $$subdir && $(MAKE) $@) || exit; \ ++ done; ++ $(MAKE) $(AM_MAKEFLAGS) install-data-hook ++ ++uninstall-hook: ++ @list='$(xineplug_LTLIBRARIES)'; for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " rm -f $(DESTDIR)$(xineplugdir)/$$p"; \ ++ rm -f $(DESTDIR)$(xineplugdir)/$$p; \ ++ done; ++ @list='$(xinepost_LTLIBRARIES)'; for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " rm -f $(DESTDIR)$(xinepostdir)/$$p"; \ ++ rm -f $(DESTDIR)$(xinepostdir)/$$p; \ ++ done; ++ @list='$(vidix_LTLIBRARIES)'; for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " rm -f $(DESTDIR)$(vidixdir)/$$p"; \ ++ rm -f $(DESTDIR)$(vidixdir)/$$p; \ ++ done; ++ ++mostlyclean-generic: ++ -rm -f *~ \#* .*~ .\#* ++ ++maintainer-clean-generic: ++ -@echo "This command is intended for maintainers to use;" ++ -@echo "it deletes files that may require special tools to rebuild." ++ -rm -f Makefile.in ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: +--- xine-lib-1.1.19.orig/src/video_out/video_out_raw.c ++++ xine-lib-1.1.19/src/video_out/video_out_raw.c +@@ -163,11 +163,16 @@ static int raw_process_ovl( raw_driver_t + clr = rle->color; + alpha = trans[clr]; + for ( i=0; iyuv2rgb->dispose (frame->yuv2rgb); + +- free (frame->chunk[0]); +- free (frame->chunk[1]); +- free (frame->chunk[2]); +- free (frame->chunk[3]); ++ if ( frame->chunk[0] ) ++ free (frame->chunk[0]); ++ if ( frame->chunk[1] ) ++ free (frame->chunk[1]); ++ if ( frame->chunk[2] ) ++ free (frame->chunk[2]); ++ if ( frame->chunk[3] ) ++ free (frame->chunk[3]); + free (frame); + } + +@@ -296,6 +305,9 @@ static vo_frame_t *raw_alloc_frame (vo_d + + if (!frame) + return NULL; ++ ++ frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = frame->chunk[3] = NULL; ++ frame->width = frame->height = frame->format = frame->flags = 0; + + pthread_mutex_init (&frame->vo_frame.mutex, NULL); + +@@ -330,13 +342,16 @@ static void raw_update_frame_format (vo_ + || (frame->flags != flags)) { + /* lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ + +- flags &= VO_BOTH_FIELDS; +- + /* (re-) allocate render space */ +- free (frame->chunk[0]); +- free (frame->chunk[1]); +- free (frame->chunk[2]); +- free (frame->chunk[3]); ++ if ( frame->chunk[0] ) ++ free (frame->chunk[0]); ++ if ( frame->chunk[1] ) ++ free (frame->chunk[1]); ++ if ( frame->chunk[2] ) ++ free (frame->chunk[2]); ++ if ( frame->chunk[3] ) ++ free (frame->chunk[3]); ++ frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = frame->chunk[3] = NULL; + + if (format == XINE_IMGFMT_YV12) { + frame->vo_frame.pitches[0] = 8*((width + 7) / 8); +@@ -355,7 +370,7 @@ static void raw_update_frame_format (vo_ + (void **) &frame->chunk[3]); + + /* set up colorspace converter */ +- switch (flags) { ++ switch (flags & VO_BOTH_FIELDS) { + case VO_TOP_FIELD: + case VO_BOTTOM_FIELD: + frame->yuv2rgb->configure (frame->yuv2rgb, +@@ -382,6 +397,7 @@ static void raw_update_frame_format (vo_ + frame->width = width; + frame->height = height; + frame->format = format; ++ frame->flags = flags; + + raw_frame_field ((vo_frame_t *)frame, flags); + } +--- xine-lib-1.1.19.orig/src/video_out/Makefile.am ++++ xine-lib-1.1.19/src/video_out/Makefile.am +@@ -37,6 +37,10 @@ endif + endif + endif + ++if HAVE_VDPAU ++vdpau_module = xineplug_vo_out_vdpau.la ++endif ++ + if HAVE_XCB + XCBOSD = xcbosd.c + if HAVE_XCBSHM +@@ -109,9 +113,15 @@ xineplug_LTLIBRARIES = $(xshm_module) $( + $(xxmc_module) \ + $(xcbshm_module) \ + $(xcbxv_module) \ ++ $(vdpau_module) \ ++ $(rawvdpau_module) \ + xineplug_vo_out_raw.la \ + xineplug_vo_out_none.la + ++xineplug_vo_out_vdpau_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_vdpau.c ++xineplug_vo_out_vdpau_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) -lvdpau ++xineplug_vo_out_vdpau_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(X_CFLAGS) ++ + xineplug_vo_out_xcbshm_la_SOURCES = video_out_xcbshm.c $(XCBOSD) + xineplug_vo_out_xcbshm_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL) + xineplug_vo_out_xcbshm_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS) +--- xine-lib-1.1.19.orig/src/video_out/xvmc_vld.c ++++ xine-lib-1.1.19/src/video_out/xvmc_vld.c +@@ -32,12 +32,12 @@ void xvmc_vld_frame(struct vo_frame_s *t + { + vo_frame_t *this = (vo_frame_t *) this_gen; + xxmc_frame_t +- *cf = (xxmc_frame_t *) this; ++ *cf = XXMC_FRAME(this); + xine_vld_frame_t + *vft = &(cf->xxmc_data.vld_frame); + xxmc_frame_t +- *ff = (xxmc_frame_t *) vft->forward_reference_frame, +- *bf = (xxmc_frame_t *) vft->backward_reference_frame; ++ *ff = XXMC_FRAME(vft->forward_reference_frame), ++ *bf = XXMC_FRAME(vft->backward_reference_frame); + XvMCMpegControl ctl; + xxmc_driver_t + *driver = (xxmc_driver_t *) cf->vo_frame.driver; +@@ -104,7 +104,7 @@ void xvmc_vld_frame(struct vo_frame_s *t + void xvmc_vld_slice(vo_frame_t *this_gen) + { + xxmc_frame_t +- *cf = (xxmc_frame_t *) this_gen; ++ *cf = XXMC_FRAME(this_gen); + xxmc_driver_t + *driver = (xxmc_driver_t *) cf->vo_frame.driver; + +--- xine-lib-1.1.19.orig/src/video_out/video_out_xv.c ++++ xine-lib-1.1.19/src/video_out/video_out_xv.c +@@ -911,6 +911,8 @@ static void xv_property_callback (void * + static int xv_set_property (vo_driver_t *this_gen, + int property, int value) { + xv_driver_t *this = (xv_driver_t *) this_gen; ++ ++ printf("xv_set_property: property=%d, value=%d\n", property, value ); + + if (this->props[property].atom != None) { + +--- xine-lib-1.1.19.orig/src/video_out/video_out_xxmc.c ++++ xine-lib-1.1.19/src/video_out/video_out_xxmc.c +@@ -365,15 +365,15 @@ static int xxmc_lock_and_validate_surfac + + switch(pc_type) { + case XINE_PICT_B_TYPE: +- frame = (xxmc_frame_t *) bw_frame; ++ frame = XXMC_FRAME(bw_frame); + if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break; + /* fall through */ + case XINE_PICT_P_TYPE: +- frame = (xxmc_frame_t *) fw_frame; ++ frame = XXMC_FRAME(fw_frame); + if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break; + /* fall through */ + default: +- frame = (xxmc_frame_t *) cur_frame; ++ frame = XXMC_FRAME(cur_frame); + if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break; + return 0; + } +@@ -404,7 +404,7 @@ static void xvmc_flush(vo_frame_t *this_ + { + + xxmc_frame_t +- *frame = (xxmc_frame_t *) this_gen; ++ *frame = XXMC_FRAME(this_gen); + xxmc_driver_t + *driver = (xxmc_driver_t *) this_gen->driver; + +@@ -452,6 +452,7 @@ static void xxmc_duplicate_frame_data(vo + return; + } + this->xxmc_data = *xxmc; ++ this->xxmc_data.xvmc.vo_frame = &this->vo_frame; + this->width = original->width; + this->height = original->height; + this->format = original->format; +@@ -566,6 +567,7 @@ static vo_frame_t *xxmc_alloc_frame (vo_ + frame->vo_frame.driver = this_gen; + frame->last_sw_format = 0; + frame->vo_frame.accel_data = &frame->xxmc_data; ++ frame->xxmc_data.xvmc.vo_frame = &frame->vo_frame; + frame->image = NULL; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "Allocating frame\n"); +@@ -1213,10 +1215,17 @@ static void xxmc_do_update_frame(vo_driv + double ratio, int format, int flags) { + + xxmc_driver_t *this = (xxmc_driver_t *) this_gen; +- xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen; ++ xxmc_frame_t *frame = XXMC_FRAME(frame_gen); + + if ( XINE_IMGFMT_XXMC == format ) { + xine_xxmc_t *xxmc = &frame->xxmc_data; ++ vo_frame_t orig_frame_content; ++ ++ if (frame_gen != &frame->vo_frame) { ++ /* this is an intercepted frame, so we need to detect and propagate any ++ * changes on the original vo_frame to all the intercepted frames */ ++ xine_fast_memcpy(&orig_frame_content, &frame->vo_frame, sizeof (vo_frame_t)); ++ } + + xvmc_context_writer_lock( &this->xvmc_lock); + if (xxmc_accel_update(this, this->last_accel_request, xxmc->acceleration) || +@@ -1232,7 +1241,7 @@ static void xxmc_do_update_frame(vo_driv + if (this->contextActive) + xxmc_frame_updates(this, frame, 1); + +- xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio, ++ xxmc_do_update_frame_xv(this_gen, &frame->vo_frame, width, height, ratio, + xxmc->fallback_format, flags); + + if (!this->contextActive) { +@@ -1246,6 +1255,33 @@ static void xxmc_do_update_frame(vo_driv + + xvmc_context_writer_unlock( &this->xvmc_lock); + ++ if (frame_gen != &frame->vo_frame) { ++ /* this is an intercepted frame, so we need to detect and propagate any ++ * changes on the original vo_frame to all the intercepted frames */ ++ unsigned char *p0 = (unsigned char *)&orig_frame_content; ++ unsigned char *p1 = (unsigned char *)&frame->vo_frame; ++ int i; ++ for (i = 0; i < sizeof (vo_frame_t); i++) { ++ if (*p0 != *p1) { ++ /* propagate the change */ ++ vo_frame_t *f = frame_gen; ++ while (f->next) { ++ /* serveral restrictions apply when intercepting XXMC frames. So let's check ++ * the intercepted frames before modifing them and fail otherwise. */ ++ unsigned char *p = (unsigned char *)f + i; ++ if (*p != *p0) { ++ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "xxmc_do_update_frame: a post plugin violates the restrictions on intercepting XXMC frames\n"); ++ _x_abort(); ++ } ++ ++ *p = *p1; ++ f = f->next; ++ } ++ } ++ p0++; ++ p1++; ++ } ++ } + } else { + /* switch back to an unaccelerated context */ + if (this->last_accel_request != 0xFFFFFFFF) { +@@ -1253,7 +1289,7 @@ static void xxmc_do_update_frame(vo_driv + xxmc_xvmc_update_context(this, frame, width, height, 0); + } + frame->vo_frame.proc_duplicate_frame_data = NULL; +- xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio, ++ xxmc_do_update_frame_xv(this_gen, &frame->vo_frame, width, height, ratio, + format, flags); + } + } +--- xine-lib-1.1.19.orig/src/video_out/video_out_xvmc.c ++++ xine-lib-1.1.19/src/video_out/video_out_xvmc.c +@@ -486,9 +486,9 @@ static void xvmc_render_macro_blocks(vo_ + int second_field, + xvmc_macroblocks_t *macroblocks) { + xvmc_driver_t *this = (xvmc_driver_t *) current_image->driver; +- xvmc_frame_t *current_frame = (xvmc_frame_t *) current_image; +- xvmc_frame_t *forward_frame = (xvmc_frame_t *) forward_ref_image; +- xvmc_frame_t *backward_frame = (xvmc_frame_t *) backward_ref_image; ++ xvmc_frame_t *current_frame = XVMC_FRAME(current_image); ++ xvmc_frame_t *forward_frame = XVMC_FRAME(forward_ref_image); ++ xvmc_frame_t *backward_frame = XVMC_FRAME(backward_ref_image); + int flags; + + lprintf ("xvmc_render_macro_blocks\n"); +@@ -561,6 +561,7 @@ static vo_frame_t *xvmc_alloc_frame (vo_ + return NULL; + + frame->vo_frame.accel_data = &frame->xvmc_data; ++ frame->xvmc_data.vo_frame = &frame->vo_frame; + + /* keep track of frames and how many frames alocated. */ + this->frames[this->num_frame_buffers++] = frame; +--- /dev/null ++++ xine-lib-1.1.19/src/video_out/video_out_vdpau.c +@@ -0,0 +1,2755 @@ ++/* ++ * Copyright (C) 2008 the xine project ++ * Copyright (C) 2008 Christophe Thommeret ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ++ * ++ * ++ * video_out_vdpau.c, a video output plugin ++ * using VDPAU (Video Decode and Presentation Api for Unix) ++ * ++ * ++ */ ++ ++/* #define LOG */ ++#define LOG_MODULE "video_out_vdpau" ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xine.h" ++#include "video_out.h" ++#include "vo_scale.h" ++#include "xine_internal.h" ++#include "yuv2rgb.h" ++#include "xineutils.h" ++ ++#include ++#include "accel_vdpau.h" ++ ++#define NUM_FRAMES_BACK 1 ++ ++#define DEINT_BOB 1 ++#define DEINT_HALF_TEMPORAL 2 ++#define DEINT_HALF_TEMPORAL_SPATIAL 3 ++#define DEINT_TEMPORAL 4 ++#define DEINT_TEMPORAL_SPATIAL 5 ++ ++#define NUMBER_OF_DEINTERLACERS 5 ++ ++char *vdpau_deinterlacer_name[] = { ++ "bob", ++ "half temporal", ++ "half temporal_spatial", ++ "temporal", ++ "temporal_spatial", ++ NULL ++}; ++ ++char* vdpau_deinterlacer_description [] = { ++ "bob\nBasic deinterlacing, doing 50i->50p.\n\n", ++ "half temporal\nDisplays first field only, doing 50i->25p\n\n", ++ "half temporal_spatial\nDisplays first field only, doing 50i->25p\n\n", ++ "temporal\nVery good, 50i->50p\n\n", ++ "temporal_spatial\nThe best, but very GPU intensive.\n\n", ++ NULL ++}; ++ ++ ++char *vdpau_sd_only_properties[] = { ++ "none", ++ "noise", ++ "sharpness", ++ "noise+sharpness", ++ NULL ++}; ++ ++VdpOutputSurfaceRenderBlendState blend = { ++ VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, ++ VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, ++ VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, ++ VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, ++ VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, ++ VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, ++ VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, ++ 0 ++}; ++ ++ ++ ++VdpDevice vdp_device; ++VdpPresentationQueue vdp_queue; ++VdpPresentationQueueTarget vdp_queue_target; ++ ++VdpDeviceDestroy *vdp_device_destroy; ++ ++VdpGetProcAddress *vdp_get_proc_address; ++ ++VdpGetApiVersion *vdp_get_api_version; ++VdpGetInformationString *vdp_get_information_string; ++VdpGetErrorString *vdp_get_error_string; ++ ++VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_get_put_bits_ycbcr_capabilities; ++VdpVideoSurfaceCreate *vdp_video_surface_create; ++VdpVideoSurfaceDestroy *vdp_video_surface_destroy; ++VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_putbits_ycbcr; ++VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_getbits_ycbcr; ++ ++VdpOutputSurfaceCreate *vdp_output_surface_create; ++VdpOutputSurfaceDestroy *vdp_output_surface_destroy; ++VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; ++VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; ++VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits; ++VdpOutputSurfaceGetBitsNative *vdp_output_surface_get_bits; ++ ++VdpVideoMixerCreate *vdp_video_mixer_create; ++VdpVideoMixerDestroy *vdp_video_mixer_destroy; ++VdpVideoMixerRender *vdp_video_mixer_render; ++VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; ++VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables; ++VdpVideoMixerGetFeatureEnables *vdp_video_mixer_get_feature_enables; ++VdpVideoMixerQueryFeatureSupport *vdp_video_mixer_query_feature_support; ++VdpVideoMixerQueryParameterSupport *vdp_video_mixer_query_parameter_support; ++VdpVideoMixerQueryAttributeSupport *vdp_video_mixer_query_attribute_support; ++VdpVideoMixerQueryParameterValueRange *vdp_video_mixer_query_parameter_value_range; ++VdpVideoMixerQueryAttributeValueRange *vdp_video_mixer_query_attribute_value_range; ++ ++VdpGenerateCSCMatrix *vdp_generate_csc_matrix; ++ ++VdpPresentationQueueTargetCreateX11 *vdp_queue_target_create_x11; ++VdpPresentationQueueTargetDestroy *vdp_queue_target_destroy; ++VdpPresentationQueueCreate *vdp_queue_create; ++VdpPresentationQueueDestroy *vdp_queue_destroy; ++VdpPresentationQueueDisplay *vdp_queue_display; ++VdpPresentationQueueBlockUntilSurfaceIdle *vdp_queue_block; ++VdpPresentationQueueSetBackgroundColor *vdp_queue_set_background_color; ++VdpPresentationQueueGetTime *vdp_queue_get_time; ++VdpPresentationQueueQuerySurfaceStatus *vdp_queue_query_surface_status; ++ ++VdpBitmapSurfacePutBitsNative *vdp_bitmap_put_bits; ++VdpBitmapSurfaceCreate *vdp_bitmap_create; ++VdpBitmapSurfaceDestroy *vdp_bitmap_destroy; ++ ++VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; ++VdpDecoderCreate *vdp_decoder_create; ++VdpDecoderDestroy *vdp_decoder_destroy; ++VdpDecoderRender *vdp_decoder_render; ++ ++VdpPreemptionCallbackRegister *vdp_preemption_callback_register; ++ ++static void vdp_preemption_callback( VdpDevice device, void *context ); ++static void vdpau_reinit( vo_driver_t *this_gen ); ++ ++static VdpVideoSurfaceCreate *orig_vdp_video_surface_create; ++static VdpVideoSurfaceDestroy *orig_vdp_video_surface_destroy; ++ ++static VdpDecoderCreate *orig_vdp_decoder_create; ++static VdpDecoderDestroy *orig_vdp_decoder_destroy; ++static VdpDecoderRender *orig_vdp_decoder_render; ++ ++static Display *guarded_display; ++ ++static VdpStatus guarded_vdp_video_surface_create(VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height,VdpVideoSurface *surface) ++{ ++ VdpStatus r; ++#ifdef LOCKDISPLAY ++ XLockDisplay(guarded_display); ++#endif ++ r = orig_vdp_video_surface_create(device, chroma_type, width, height, surface); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay(guarded_display); ++#endif ++ return r; ++} ++ ++static VdpStatus guarded_vdp_video_surface_destroy(VdpVideoSurface surface) ++{ ++ VdpStatus r; ++ /*XLockDisplay(guarded_display);*/ ++ r = orig_vdp_video_surface_destroy(surface); ++ /*XUnlockDisplay(guarded_display);*/ ++ return r; ++} ++ ++static VdpStatus guarded_vdp_decoder_create(VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder) ++{ ++ VdpStatus r; ++#ifdef LOCKDISPLAY ++ XLockDisplay(guarded_display); ++#endif ++ r = orig_vdp_decoder_create(device, profile, width, height, max_references, decoder); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay(guarded_display); ++#endif ++ return r; ++} ++ ++static VdpStatus guarded_vdp_decoder_destroy(VdpDecoder decoder) ++{ ++ VdpStatus r; ++#ifdef LOCKDISPLAY ++ XLockDisplay(guarded_display); ++#endif ++ r = orig_vdp_decoder_destroy(decoder); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay(guarded_display); ++#endif ++ return r; ++} ++ ++static VdpStatus guarded_vdp_decoder_render(VdpDecoder decoder, VdpVideoSurface target, VdpPictureInfo const *picture_info, uint32_t bitstream_buffer_count, VdpBitstreamBuffer const *bitstream_buffers) ++{ ++ VdpStatus r; ++#ifdef LOCKDISPLAY ++ XLockDisplay(guarded_display); ++#endif ++ r = orig_vdp_decoder_render(decoder, target, picture_info, bitstream_buffer_count, bitstream_buffers); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay(guarded_display); ++#endif ++ return r; ++} ++ ++ ++ ++typedef struct { ++ VdpBitmapSurface ovl_bitmap; ++ uint32_t bitmap_width, bitmap_height; ++ int ovl_w, ovl_h; /* overlay's width and height */ ++ int ovl_x, ovl_y; /* overlay's top-left display position */ ++ int unscaled; ++ int expected_overlay_width; /*if >0 scale to video width*/ ++ int expected_overlay_height; /* if >0 scale to video height */ ++} vdpau_overlay_t; ++ ++ ++typedef struct { ++ int x; ++ int y; ++ int w; ++ int h; ++} ++argb_ovl_data_t; ++ ++ ++typedef struct { ++ vo_frame_t vo_frame; ++ ++ int width, height, format, flags; ++ double ratio; ++ uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ ++ ++ vdpau_accel_t vdpau_accel_data; ++} vdpau_frame_t; ++ ++ ++typedef struct { ++ ++ vo_driver_t vo_driver; ++ vo_scale_t sc; ++ ++ Display *display; ++ int screen; ++ Drawable drawable; ++ ++ config_values_t *config; ++ ++ int ovl_changed; ++ vdpau_overlay_t overlays[XINE_VORAW_MAX_OVL]; ++ yuv2rgb_factory_t *yuv2rgb_factory; ++ yuv2rgb_t *ovl_yuv2rgb; ++ VdpOutputSurface overlay_output; ++ uint32_t overlay_output_width; ++ uint32_t overlay_output_height; ++ int has_overlay; ++ ++ VdpOutputSurface overlay_unscaled; ++ uint32_t overlay_unscaled_width; ++ uint32_t overlay_unscaled_height; ++ int has_unscaled; ++ ++ int32_t video_window_x; ++ int32_t video_window_y; ++ int32_t video_window_width; ++ int32_t video_window_height; ++ ++ VdpVideoSurface soft_surface; ++ uint32_t soft_surface_width; ++ uint32_t soft_surface_height; ++ int soft_surface_format; ++ ++#define NOUTPUTSURFACE 4 ++ VdpOutputSurface output_surface[NOUTPUTSURFACE]; ++ uint8_t current_output_surface; ++ uint32_t output_surface_width[NOUTPUTSURFACE]; ++ uint32_t output_surface_height[NOUTPUTSURFACE]; ++ uint8_t init_queue; ++ uint8_t queue_length; ++ uint64_t output_surface_vpts[NOUTPUTSURFACE]; ++ pthread_mutex_t output_surface_lock[NOUTPUTSURFACE]; ++ pthread_cond_t queue_changed; ++ pthread_mutex_t queue_lock; ++ ++ VdpVideoMixer video_mixer; ++ VdpChromaType video_mixer_chroma; ++ uint32_t video_mixer_width; ++ uint32_t video_mixer_height; ++ VdpColorStandard color_standard; ++ VdpBool temporal_spatial_is_supported; ++ VdpBool temporal_is_supported; ++ VdpBool noise_reduction_is_supported; ++ VdpBool sharpness_is_supported; ++ VdpBool inverse_telecine_is_supported; ++ VdpBool skip_chroma_is_supported; ++ ++ char* deinterlacers_name[NUMBER_OF_DEINTERLACERS+1]; ++ int deinterlacers_method[NUMBER_OF_DEINTERLACERS]; ++ ++ int scaling_level_max; ++ int scaling_level_current; ++ ++ VdpColor back_color; ++ ++ vdpau_frame_t *back_frame[ NUM_FRAMES_BACK ]; ++ ++ uint32_t capabilities; ++ xine_t *xine; ++ ++ int hue; ++ int saturation; ++ int brightness; ++ int contrast; ++ int sharpness; ++ int noise; ++ int deinterlace; ++ int deinterlace_method; ++ int enable_inverse_telecine; ++ int honor_progressive; ++ int skip_chroma; ++ int sd_only_properties; ++ ++ int vdp_runtime_nr; ++ int reinit_needed; ++ ++ int allocated_surfaces; ++ int zoom_x; ++ int zoom_y; ++} vdpau_driver_t; ++ ++ ++typedef struct { ++ video_driver_class_t driver_class; ++ xine_t *xine; ++} vdpau_class_t; ++ ++ ++ ++static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *overlay, vdpau_frame_t *frame) ++{ ++ int i; ++ clut_t* clut = (clut_t*) overlay->color; ++ ++ if (!overlay->rgb_clut) { ++ for ( i=0; icolor)/sizeof(overlay->color[0]); i++ ) { ++ *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); ++ } ++ overlay->rgb_clut++; ++ } ++ if (!overlay->hili_rgb_clut) { ++ clut = (clut_t*) overlay->hili_color; ++ for ( i=0; icolor)/sizeof(overlay->color[0]); i++) { ++ *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); ++ } ++ overlay->hili_rgb_clut++; ++ } ++} ++ ++ ++ ++static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) ++{ ++ vdpau_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1]; ++ ++ if ( overlay->width<=0 || overlay->height<=0 ) ++ return 0; ++ ++ ovl->ovl_w = overlay->width; ++ ovl->ovl_h = overlay->height; ++ ovl->ovl_x = overlay->x; ++ ovl->ovl_y = overlay->y; ++ ovl->unscaled = overlay->unscaled; ++ ovl->expected_overlay_width = overlay->extent_width; ++ ovl->expected_overlay_height = overlay->extent_height; ++ ++ if (overlay->video_window_width > 0 && overlay->video_window_height > 0) { ++ /* last one wins */ ++ this_gen->video_window_x = overlay->video_window_x; ++ this_gen->video_window_y = overlay->video_window_y; ++ this_gen->video_window_width = overlay->video_window_width; ++ this_gen->video_window_height = overlay->video_window_height; ++ } ++ ++ if ( (ovl->bitmap_width < overlay->width ) || (ovl->bitmap_height < overlay->height) || (ovl->ovl_bitmap == VDP_INVALID_HANDLE) ) { ++ if (ovl->ovl_bitmap != VDP_INVALID_HANDLE) { ++ vdp_bitmap_destroy( ovl->ovl_bitmap ); ++ ovl->ovl_bitmap = VDP_INVALID_HANDLE; ++ } ++ VdpStatus st = vdp_bitmap_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, 0, &ovl->ovl_bitmap ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_process_ovl: vdp_bitmap_create failed : %s\n", vdp_get_error_string(st) ); ++ return 0; ++ } ++ ovl->bitmap_width = overlay->width; ++ ovl->bitmap_height = overlay->height; ++ } ++ ++ if (overlay->rle) { ++ uint32_t *buf = (uint32_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); ++ if ( !buf ) ++ return 0; ++ ++ int num_rle = overlay->num_rle; ++ rle_elem_t *rle = overlay->rle; ++ uint32_t *rgba = buf; ++ uint32_t red, green, blue, alpha; ++ clut_t *low_colors = (clut_t*)overlay->color; ++ clut_t *hili_colors = (clut_t*)overlay->hili_color; ++ uint8_t *low_trans = overlay->trans; ++ uint8_t *hili_trans = overlay->hili_trans; ++ clut_t *colors; ++ uint8_t *trans; ++ int rlelen = 0; ++ uint8_t clr = 0; ++ int i, pos=0, x, y; ++ ++ while ( num_rle>0 ) { ++ x = pos%ovl->ovl_w; ++ y = pos/ovl->ovl_w; ++ if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) { ++ colors = hili_colors; ++ trans = hili_trans; ++ } ++ else { ++ colors = low_colors; ++ trans = low_trans; ++ } ++ rlelen = rle->len; ++ clr = rle->color; ++ for ( i=0; iovl_w*4; ++ VdpRect dest = { 0, 0, ovl->ovl_w, ovl->ovl_h }; ++ VdpStatus st = vdp_bitmap_put_bits( ovl->ovl_bitmap, &buf, &pitch, &dest); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_process_ovl: vdp_bitmap_put_bits failed : %s\n", vdp_get_error_string(st) ); ++ } ++ free(buf); ++ } ++ else if (overlay->argb_layer) { ++ pthread_mutex_lock(&overlay->argb_layer->mutex); ++ if (overlay->argb_layer->buffer) { ++ uint32_t pitch = ovl->ovl_w*4; ++ VdpRect dest = { 0, 0, ovl->ovl_w, ovl->ovl_h }; ++ VdpStatus st = vdp_bitmap_put_bits( ovl->ovl_bitmap, &overlay->argb_layer->buffer, &pitch, &dest); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_process_ovl: vdp_bitmap_put_bits failed : %s\n", vdp_get_error_string(st) ); ++ } ++ } ++ pthread_mutex_unlock(&overlay->argb_layer->mutex); ++ } ++ ++ return 1; ++} ++ ++ ++ ++static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ if ( !changed ) ++ return; ++ ++ this->has_overlay = this->has_unscaled = 0; ++ this->video_window_x = 0; ++ this->video_window_y = 0; ++ this->video_window_width = 0; ++ this->video_window_height = 0; ++ ++this->ovl_changed; ++} ++ ++ ++ ++static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; ++ ++ if (!this->ovl_changed) ++ return; ++ ++ if (this->ovl_changed >= XINE_VORAW_MAX_OVL) ++ return; ++ ++ if (overlay->rle) { ++ if (!overlay->rgb_clut || !overlay->hili_rgb_clut) ++ vdpau_overlay_clut_yuv2rgb (this, overlay, frame); ++ } ++ ++ if ( vdpau_process_ovl( this, overlay ) ) ++ ++this->ovl_changed; ++} ++ ++ ++ ++static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ int i; ++ VdpStatus st; ++ ++ if ( !this->ovl_changed ) ++ return; ++ ++ if ( !(this->ovl_changed-1) ) { ++ this->ovl_changed = 0; ++ this->has_overlay = 0; ++ this->has_unscaled = 0; ++ return; ++ } ++ ++ int w=0, h=0; ++ int scaler = 0; ++ for ( i=0; iovl_changed-1; ++i ) { ++ if ( this->overlays[i].unscaled ) ++ continue; ++ if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) ) ++ w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; ++ if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) ) ++ h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; ++ if ( this->overlays[i].expected_overlay_width ) ++ scaler = 1; ++ if ( this->overlays[i].expected_overlay_height ) ++ scaler = 1; ++ this->has_overlay = 1; ++ } ++ ++ if ( scaler ) { ++ w = this->video_mixer_width; ++ h = this->video_mixer_height; ++ } ++ ++ int out_w = (w>frame->width) ? w : frame->width; ++ int out_h = (h>frame->height) ? h : frame->height; ++ ++ if ( (!this->has_overlay || this->overlay_output_width!=out_w || this->overlay_output_height!=out_h) && this->overlay_output != VDP_INVALID_HANDLE ) { ++ st = vdp_output_surface_destroy( this->overlay_output ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); ++ } ++ this->overlay_output = VDP_INVALID_HANDLE; ++ } ++ ++ this->overlay_output_width = out_w; ++ this->overlay_output_height = out_h; ++ ++ w = 64; h = 64; ++ for ( i=0; iovl_changed-1; ++i ) { ++ if ( !this->overlays[i].unscaled ) ++ continue; ++ if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) ) ++ w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; ++ if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) ) ++ h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; ++ this->has_unscaled = 1; ++ } ++ ++ if ( (!this->has_unscaled || this->overlay_unscaled_width!=w || this->overlay_unscaled_height!=h) && this->overlay_unscaled != VDP_INVALID_HANDLE ) { ++ st = vdp_output_surface_destroy( this->overlay_unscaled ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); ++ } ++ this->overlay_unscaled = VDP_INVALID_HANDLE; ++ } ++ ++ this->overlay_unscaled_width = w; ++ this->overlay_unscaled_height = h; ++ ++ if ( this->has_unscaled && this->overlay_unscaled == VDP_INVALID_HANDLE ) { ++ st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_unscaled_width, this->overlay_unscaled_height, &this->overlay_unscaled ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); ++ } ++ ++ if ( this->has_overlay && this->overlay_output == VDP_INVALID_HANDLE ) { ++ st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_output_width, this->overlay_output_height, &this->overlay_output ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); ++ } ++ ++ w = (this->overlay_unscaled_width>this->overlay_output_width) ? this->overlay_unscaled_width : this->overlay_output_width; ++ h = (this->overlay_unscaled_height>this->overlay_output_height) ? this->overlay_unscaled_height : this->overlay_output_height; ++ ++ uint32_t *buf = (uint32_t*)calloc(w*4,h); ++ uint32_t pitch = w*4; ++ VdpRect clear = { 0, 0, this->overlay_output_width, this->overlay_output_height }; ++ if (this->has_overlay) { ++ st = vdp_output_surface_put_bits( this->overlay_output, &buf, &pitch, &clear ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); ++ } ++ } ++ if (this->has_unscaled) { ++ clear.x1 = this->overlay_unscaled_width; clear.y1 = this->overlay_unscaled_height; ++ st = vdp_output_surface_put_bits( this->overlay_unscaled, &buf, &pitch, &clear ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); ++ } ++ } ++ free(buf); ++ ++ VdpOutputSurface *surface; ++ for ( i=0; iovl_changed-1; ++i ) { ++ VdpRect dest = { this->overlays[i].ovl_x, this->overlays[i].ovl_y, this->overlays[i].ovl_x+this->overlays[i].ovl_w, this->overlays[i].ovl_y+this->overlays[i].ovl_h }; ++ if ( !this->overlays[i].unscaled && this->overlays[i].expected_overlay_width ) { ++ double rx = (double)this->overlay_output_width/(double)this->overlays[i].expected_overlay_width; ++ double ry = (double)this->overlay_output_height/(double)this->overlays[i].expected_overlay_height; ++ dest.x0 *= rx; dest.y0 *= ry; dest.x1 *=rx; dest.y1 *= ry; ++ lprintf( "vdpau_overlay_end: overlay_width=%d overlay_height=%d rx=%f ry=%f\n", this->overlay_output_width, this->overlay_output_height, rx, ry ); ++ } ++ VdpRect src = { 0, 0, this->overlays[i].ovl_w, this->overlays[i].ovl_h }; ++ surface = (this->overlays[i].unscaled) ? &this->overlay_unscaled : &this->overlay_output; ++ st = vdp_output_surface_render_bitmap_surface( *surface, &dest, this->overlays[i].ovl_bitmap, &src, 0, &blend, 0 ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vdpau_overlay_end: vdp_output_surface_render_bitmap_surface failed : %s\n", vdp_get_error_string(st) ); ++ } ++ } ++ this->ovl_changed = 0; ++} ++ ++ ++ ++static void vdpau_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) ++{ ++ vdpau_frame_t *frame = (vdpau_frame_t *) vo_img ; ++ ++ vo_img->proc_called = 1; ++} ++ ++ ++ ++static void vdpau_frame_field (vo_frame_t *vo_img, int which_field) ++{ ++} ++ ++ ++ ++static void vdpau_frame_dispose (vo_frame_t *vo_img) ++{ ++ vdpau_frame_t *frame = (vdpau_frame_t *) vo_img ; ++ ++ if ( frame->chunk[0] ) ++ free (frame->chunk[0]); ++ if ( frame->chunk[1] ) ++ free (frame->chunk[1]); ++ if ( frame->chunk[2] ) ++ free (frame->chunk[2]); ++ if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) ++ vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); ++ free (frame); ++} ++ ++ ++ ++static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) ++{ ++ vdpau_frame_t *frame; ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ lprintf( "vo_vdpau: vdpau_alloc_frame\n" ); ++ ++ frame = (vdpau_frame_t *) calloc(1, sizeof(vdpau_frame_t)); ++ ++ if (!frame) ++ return NULL; ++ ++ frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = NULL; ++ frame->width = frame->height = frame->format = frame->flags = 0; ++ ++ frame->vo_frame.accel_data = &frame->vdpau_accel_data; ++ ++ pthread_mutex_init (&frame->vo_frame.mutex, NULL); ++ ++ /* ++ * supply required functions/fields ++ */ ++ frame->vo_frame.proc_duplicate_frame_data = NULL; ++ frame->vo_frame.proc_slice = vdpau_frame_proc_slice; ++ frame->vo_frame.proc_frame = NULL; ++ frame->vo_frame.field = vdpau_frame_field; ++ frame->vo_frame.dispose = vdpau_frame_dispose; ++ frame->vo_frame.driver = this_gen; ++ ++ frame->vdpau_accel_data.vo_frame = &frame->vo_frame; ++ frame->vdpau_accel_data.vdp_device = vdp_device; ++ frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; ++ frame->vdpau_accel_data.chroma = VDP_CHROMA_TYPE_420; ++ frame->vdpau_accel_data.color_standard = this->color_standard; ++ frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create; ++ frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy; ++ frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; ++ frame->vdpau_accel_data.vdp_get_error_string = vdp_get_error_string; ++ frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr; ++ frame->vdpau_accel_data.current_vdp_runtime_nr = &this->vdp_runtime_nr; ++ ++ return (vo_frame_t *) frame; ++} ++ ++ ++static void vdpau_provide_standard_frame_data (vo_frame_t *this, xine_current_frame_data_t *data) ++{ ++ VdpStatus st; ++ VdpYCbCrFormat format; ++ uint32_t pitches[3]; ++ void *base[3]; ++ ++ if (this->format != XINE_IMGFMT_VDPAU) { ++ fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->format); ++ return; ++ } ++ ++ vdpau_accel_t *accel = (vdpau_accel_t *) this->accel_data; ++ ++ if (accel->vdp_runtime_nr != *(accel->current_vdp_runtime_nr)) ++ return; ++ ++ this = accel->vo_frame; ++ ++ if (accel->chroma == VDP_CHROMA_TYPE_420) { ++ data->format = XINE_IMGFMT_YV12; ++ data->img_size = this->width * this->height ++ + ((this->width + 1) / 2) * ((this->height + 1) / 2) ++ + ((this->width + 1) / 2) * ((this->height + 1) / 2); ++ if (data->img) { ++ pitches[0] = this->width; ++ pitches[1] = this->width / 2; ++ pitches[2] = this->width / 2; ++ base[0] = data->img; ++ base[1] = data->img + this->width * this->height; ++ base[2] = data->img + this->width * this->height + this->width * this->height / 4; ++ format = VDP_YCBCR_FORMAT_YV12; ++ } ++ } else { ++ data->format = XINE_IMGFMT_YUY2; ++ data->img_size = this->width * this->height ++ + ((this->width + 1) / 2) * this->height ++ + ((this->width + 1) / 2) * this->height; ++ if (data->img) { ++ pitches[0] = this->width * 2; ++ base[0] = data->img; ++ format = VDP_YCBCR_FORMAT_YUYV; ++ } ++ } ++ ++ if (data->img) { ++ st = vdp_video_surface_getbits_ycbcr(accel->surface, format, base, pitches); ++ if (st != VDP_STATUS_OK) ++ printf("vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st)); ++ } ++} ++ ++ ++static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original) ++{ ++ vdpau_frame_t *this = (vdpau_frame_t *)this_gen; ++ vdpau_frame_t *orig = (vdpau_frame_t *)original; ++ VdpStatus st; ++ VdpYCbCrFormat format; ++ ++ if (orig->vo_frame.format != XINE_IMGFMT_VDPAU) { ++ fprintf(stderr, "vdpau_duplicate_frame_data: unexpected frame format 0x%08x!\n", orig->vo_frame.format); ++ return; ++ } ++ ++ if(orig->vdpau_accel_data.vdp_runtime_nr != this->vdpau_accel_data.vdp_runtime_nr) { ++ fprintf(stderr, "vdpau_duplicate_frame_data: called with invalid frame\n"); ++ return; ++ } ++ ++ if (!(orig->flags & VO_CHROMA_422)) { ++ this->vo_frame.pitches[0] = 8*((orig->vo_frame.width + 7) / 8); ++ this->vo_frame.pitches[1] = 8*((orig->vo_frame.width + 15) / 16); ++ this->vo_frame.pitches[2] = 8*((orig->vo_frame.width + 15) / 16); ++ this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * orig->vo_frame.height, (void **)&this->chunk[0]); ++ this->vo_frame.base[1] = xine_xmalloc_aligned(16, this->vo_frame.pitches[1] * ((orig->vo_frame.height+1)/2), (void **)&this->chunk[1]); ++ this->vo_frame.base[2] = xine_xmalloc_aligned(16, this->vo_frame.pitches[2] * ((orig->vo_frame.height+1)/2), (void **)&this->chunk[2]); ++ format = VDP_YCBCR_FORMAT_YV12; ++ } else { ++ this->vo_frame.pitches[0] = 8*((orig->vo_frame.width + 3) / 4); ++ this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * orig->vo_frame.height, (void **)&this->chunk[0]); ++ format = VDP_YCBCR_FORMAT_YUYV; ++ } ++ ++ st = vdp_video_surface_getbits_ycbcr(orig->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches); ++ if (st != VDP_STATUS_OK) ++ printf("vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st)); ++ ++ st = vdp_video_surface_putbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches); ++ if (st != VDP_STATUS_OK) ++ printf("vo_vdpau: failed to put surface bits !! %s\n", vdp_get_error_string(st)); ++ ++ this->vdpau_accel_data.color_standard = orig->vdpau_accel_data.color_standard; ++ ++ if (this->chunk[0]) ++ free(this->chunk[0]); ++ if (this->chunk[1]) ++ free(this->chunk[1]); ++ if (this->chunk[2]) ++ free(this->chunk[2]); ++ this->chunk[0] = this->chunk[1] = this->chunk[2] = NULL; ++} ++ ++ ++ ++static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, ++ uint32_t width, uint32_t height, double ratio, int format, int flags) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ vdpau_frame_t *frame = VDPAU_FRAME(frame_gen); ++ ++ VdpChromaType chroma = (flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; ++ ++ vo_frame_t orig_frame_content; ++ if (format == XINE_IMGFMT_VDPAU) { ++ if (frame_gen != &frame->vo_frame) { ++ /* this is an intercepted frame, so we need to detect and propagate any ++ * changes on the original vo_frame to all the intercepted frames */ ++ xine_fast_memcpy(&orig_frame_content, &frame->vo_frame, sizeof (vo_frame_t)); ++ } ++ } ++ ++ /* Check frame size and format and reallocate if necessary */ ++ if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) || ++ (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) { ++ ++ /* (re-) allocate render space */ ++ if ( frame->chunk[0] ) ++ free (frame->chunk[0]); ++ if ( frame->chunk[1] ) ++ free (frame->chunk[1]); ++ if ( frame->chunk[2] ) ++ free (frame->chunk[2]); ++ frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = NULL; ++ ++ if (format == XINE_IMGFMT_YV12) { ++ frame->vo_frame.pitches[0] = 8*((width + 7) / 8); ++ frame->vo_frame.pitches[1] = 8*((width + 15) / 16); ++ frame->vo_frame.pitches[2] = 8*((width + 15) / 16); ++ frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); ++ frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]); ++ frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]); ++ } else if (format == XINE_IMGFMT_YUY2){ ++ frame->vo_frame.pitches[0] = 8*((width + 3) / 4); ++ frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); ++ frame->chunk[1] = NULL; ++ frame->chunk[2] = NULL; ++ } ++ ++ if ( frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr ) { ++ frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; ++ frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr; ++ frame->vdpau_accel_data.vdp_device = vdp_device; ++ frame->vo_frame.proc_duplicate_frame_data = NULL; ++ frame->vo_frame.proc_provide_standard_frame_data = NULL; ++ } ++ ++ if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) { ++ if ( (frame->width != width) || (frame->height != height) || (format != XINE_IMGFMT_VDPAU) || frame->vdpau_accel_data.chroma != chroma ) { ++ lprintf("vo_vdpau: update_frame - destroy surface\n"); ++ vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); ++ frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; ++ --this->allocated_surfaces; ++ frame->vo_frame.proc_duplicate_frame_data = NULL; ++ frame->vo_frame.proc_provide_standard_frame_data = NULL; ++ } ++ } ++ ++ if ( (format == XINE_IMGFMT_VDPAU) && (frame->vdpau_accel_data.surface == VDP_INVALID_HANDLE) ) { ++ VdpStatus st = vdp_video_surface_create( vdp_device, chroma, width, height, &frame->vdpau_accel_data.surface ); ++ if ( st!=VDP_STATUS_OK ) ++ printf( "vo_vdpau: failed to create surface !! %s\n", vdp_get_error_string( st ) ); ++ else { ++ frame->vdpau_accel_data.chroma = chroma; ++ ++this->allocated_surfaces; ++ frame->vo_frame.proc_duplicate_frame_data = vdpau_duplicate_frame_data; ++ frame->vo_frame.proc_provide_standard_frame_data = vdpau_provide_standard_frame_data; ++ } ++ } ++ ++ frame->width = width; ++ frame->height = height; ++ frame->format = format; ++ frame->flags = flags; ++ ++ vdpau_frame_field ((vo_frame_t *)frame, flags); ++ } ++ ++ frame->vdpau_accel_data.color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; ++ frame->ratio = ratio; ++ frame->vo_frame.future_frame = NULL; ++ ++ if (format == XINE_IMGFMT_VDPAU) { ++ if (frame_gen != &frame->vo_frame) { ++ /* this is an intercepted frame, so we need to detect and propagate any ++ * changes on the original vo_frame to all the intercepted frames */ ++ unsigned char *p0 = (unsigned char *)&orig_frame_content; ++ unsigned char *p1 = (unsigned char *)&frame->vo_frame; ++ int i; ++ for (i = 0; i < sizeof (vo_frame_t); i++) { ++ if (*p0 != *p1) { ++ /* propagate the change */ ++ vo_frame_t *f = frame_gen; ++ while (f->next) { ++ /* serveral restrictions apply when intercepting VDPAU frames. So let's check ++ * the intercepted frames before modifing them and fail otherwise. */ ++ unsigned char *p = (unsigned char *)f + i; ++ if (*p != *p0) { ++ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "vdpau_update_frame_format: a post plugin violates the restrictions on intercepting VDPAU frames\n"); ++ _x_abort(); ++ } ++ ++ *p = *p1; ++ f = f->next; ++ } ++ } ++ p0++; ++ p1++; ++ } ++ } ++ } ++} ++ ++ ++ ++static int vdpau_redraw_needed (vo_driver_t *this_gen) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ _x_vo_scale_compute_ideal_size( &this->sc ); ++ if ( _x_vo_scale_redraw_needed( &this->sc ) ) { ++ _x_vo_scale_compute_output_size( &this->sc ); ++ return 1; ++ } ++ return 0; ++} ++ ++ ++ ++static void vdpau_release_back_frames( vo_driver_t *this_gen ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ int i; ++ ++ for ( i=0; iback_frame[ i ]) ++ this->back_frame[ i ]->vo_frame.free( &this->back_frame[ i ]->vo_frame ); ++ this->back_frame[ i ] = NULL; ++ } ++} ++ ++ ++ ++static void vdpau_backup_frame( vo_driver_t *this_gen, vo_frame_t *frame_gen ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; ++ ++ int i; ++ if ( this->back_frame[NUM_FRAMES_BACK-1]) { ++ this->back_frame[NUM_FRAMES_BACK-1]->vo_frame.free (&this->back_frame[NUM_FRAMES_BACK-1]->vo_frame); ++ } ++ for ( i=NUM_FRAMES_BACK-1; i>0; i-- ) ++ this->back_frame[i] = this->back_frame[i-1]; ++ this->back_frame[0] = frame; ++} ++ ++ ++ ++static void vdpau_set_deinterlace( vo_driver_t *this_gen ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ VdpVideoMixerFeature features[2]; ++ VdpBool feature_enables[2]; ++ int features_count = 0; ++ if ( this->temporal_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; ++ ++features_count; ++ } ++ if ( this->temporal_spatial_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; ++ ++features_count; ++ } ++ ++ if ( !features_count ) ++ return; ++ ++ if ( this->deinterlace ) { ++ if ( this->video_mixer_width<800 ) { ++ feature_enables[0] = feature_enables[1] = 1; ++ if ( this->temporal_is_supported ) { ++ if ( this->temporal_spatial_is_supported ) ++ printf("vo_vdpau: deinterlace: temporal_spatial\n" ); ++ else ++ printf("vo_vdpau: deinterlace: temporal\n" ); ++ } ++ else ++ printf("vo_vdpau: deinterlace: bob\n" ); ++ } ++ else { ++ switch ( this->deinterlacers_method[this->deinterlace_method] ) { ++ case DEINT_BOB: ++ feature_enables[0] = feature_enables[1] = 0; ++ printf("vo_vdpau: deinterlace: bob\n" ); ++ break; ++ case DEINT_HALF_TEMPORAL: ++ feature_enables[0] = 1; feature_enables[1] = 0; ++ printf("vo_vdpau: deinterlace: half_temporal\n" ); ++ break; ++ case DEINT_TEMPORAL: ++ feature_enables[0] = 1; feature_enables[1] = 0; ++ printf("vo_vdpau: deinterlace: temporal\n" ); ++ break; ++ case DEINT_HALF_TEMPORAL_SPATIAL: ++ feature_enables[0] = feature_enables[1] = 1; ++ printf("vo_vdpau: deinterlace: half_temporal_spatial\n" ); ++ break; ++ case DEINT_TEMPORAL_SPATIAL: ++ feature_enables[0] = feature_enables[1] = 1; ++ printf("vo_vdpau: deinterlace: temporal_spatial\n" ); ++ break; ++ } ++ } ++ } ++ else { ++ feature_enables[0] = feature_enables[1] = 0; ++ printf("vo_vdpau: deinterlace: none\n" ); ++ } ++ ++ vdp_video_mixer_set_feature_enables( this->video_mixer, features_count, features, feature_enables ); ++} ++ ++ ++ ++static void vdpau_set_inverse_telecine( vo_driver_t *this_gen ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ if ( !this->inverse_telecine_is_supported ) ++ return; ++ ++ VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE }; ++ VdpBool feature_enables[1]; ++ if ( this->deinterlace && this->enable_inverse_telecine ) ++ feature_enables[0] = 1; ++ else ++ feature_enables[0] = 0; ++ ++ vdp_video_mixer_set_feature_enables( this->video_mixer, 1, features, feature_enables ); ++ vdp_video_mixer_get_feature_enables( this->video_mixer, 1, features, feature_enables ); ++ printf("vo_vdpau: enabled features: inverse_telecine=%d\n", feature_enables[0] ); ++} ++ ++ ++ ++static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *entry ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ this->deinterlace_method = entry->num_value; ++ printf( "vo_vdpau: deinterlace_method=%d\n", this->deinterlace_method ); ++ vdpau_set_deinterlace( (vo_driver_t*)this_gen ); ++} ++ ++ ++ ++static void vdpau_set_scaling_level( vo_driver_t *this_gen ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ int i; ++ VdpVideoMixerFeature features[9]; ++ VdpBool feature_enables[9]; ++#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 ++ for ( i=0; iscaling_level_max; ++i ) { ++ features[i] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; ++ feature_enables[i] = 0; ++ } ++ vdp_video_mixer_set_feature_enables( this->video_mixer, this->scaling_level_max, features, feature_enables ); ++ ++ if ( this->scaling_level_current ) { ++ features[0] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 - 1 + this->scaling_level_current; ++ feature_enables[0] = 1; ++ vdp_video_mixer_set_feature_enables( this->video_mixer, 1, features, feature_enables ); ++ } ++ ++ printf( "vo_vdpau: set_scaling_level=%d\n", this->scaling_level_current ); ++#endif ++} ++ ++ ++ ++static void vdpau_update_scaling_level( void *this_gen, xine_cfg_entry_t *entry ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ this->scaling_level_current = entry->num_value; ++ printf( "vo_vdpau: scaling_quality=%d\n", this->scaling_level_current ); ++ vdpau_set_scaling_level( (vo_driver_t*)this_gen ); ++} ++ ++ ++ ++static void vdpau_update_enable_inverse_telecine( void *this_gen, xine_cfg_entry_t *entry ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ this->enable_inverse_telecine = entry->num_value; ++ printf( "vo_vdpau: enable inverse_telecine=%d\n", this->enable_inverse_telecine ); ++ vdpau_set_inverse_telecine( (vo_driver_t*)this_gen ); ++} ++ ++ ++ ++static void vdpau_honor_progressive_flag( void *this_gen, xine_cfg_entry_t *entry ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ this->honor_progressive = entry->num_value; ++ printf( "vo_vdpau: honor_progressive=%d\n", this->honor_progressive ); ++} ++ ++ ++ ++static void vdpau_update_noise( vdpau_driver_t *this_gen ) ++{ ++ if ( !this_gen->noise_reduction_is_supported ) ++ return; ++ ++ float value = this_gen->noise/100.0; ++ if ( value==0 || ((this_gen->sd_only_properties & 1) && this_gen->video_mixer_width >= 800)) { ++ VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; ++ VdpBool feature_enables[] = { 0 }; ++ vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); ++ printf( "vo_vdpau: disable noise reduction.\n" ); ++ return; ++ } ++ else { ++ VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; ++ VdpBool feature_enables[] = { 1 }; ++ vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); ++ printf( "vo_vdpau: enable noise reduction.\n" ); ++ } ++ ++ VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; ++ void* attribute_values[] = { &value }; ++ VdpStatus st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: error, can't set noise reduction level !!\n" ); ++} ++ ++ ++ ++static void vdpau_update_sharpness( vdpau_driver_t *this_gen ) ++{ ++ if ( !this_gen->sharpness_is_supported ) ++ return; ++ ++ float value = this_gen->sharpness/100.0; ++ if ( value==0 || (this_gen->sd_only_properties >= 2 && this_gen->video_mixer_width >= 800)) { ++ VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; ++ VdpBool feature_enables[] = { 0 }; ++ vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); ++ printf( "vo_vdpau: disable sharpness.\n" ); ++ return; ++ } ++ else { ++ VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; ++ VdpBool feature_enables[] = { 1 }; ++ vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); ++ printf( "vo_vdpau: enable sharpness.\n" ); ++ } ++ ++ VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL }; ++ void* attribute_values[] = { &value }; ++ VdpStatus st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: error, can't set sharpness level !!\n" ); ++} ++ ++ ++ ++static void vdpau_update_sd_only_properties( void *this_gen, xine_cfg_entry_t *entry ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ this->sd_only_properties = entry->num_value; ++ printf( "vo_vdpau: enable sd only noise=%d, sd only sharpness %d\n", ((this->sd_only_properties & 1) != 0), (this->sd_only_properties >= 2) ); ++ vdpau_update_noise(this); ++ vdpau_update_sharpness(this); ++} ++ ++ ++ ++static void vdpau_update_csc( vdpau_driver_t *this_gen ) ++{ ++ float hue = this_gen->hue/100.0; ++ float saturation = this_gen->saturation/100.0; ++ float contrast = this_gen->contrast/100.0; ++ float brightness = this_gen->brightness/100.0; ++ ++ printf( "vo_vdpau: vdpau_update_csc: hue=%f, saturation=%f, contrast=%f, brightness=%f, color_standard=%d\n", hue, saturation, contrast, brightness, this_gen->color_standard ); ++ ++ VdpCSCMatrix matrix; ++ VdpProcamp procamp = { VDP_PROCAMP_VERSION, brightness, contrast, saturation, hue }; ++ ++ VdpStatus st = vdp_generate_csc_matrix( &procamp, this_gen->color_standard, &matrix ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vo_vdpau: error, can't generate csc matrix !!\n" ); ++ return; ++ } ++ VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; ++ void* attribute_values[] = { &matrix }; ++ st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: error, can't set csc matrix !!\n" ); ++} ++ ++ ++ ++static void vdpau_update_skip_chroma( vdpau_driver_t *this_gen ) ++{ ++ if ( !this_gen->skip_chroma_is_supported ) ++ return; ++ ++ VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE }; ++ void* attribute_values[] = { &(this_gen->skip_chroma) }; ++ VdpStatus st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: error, can't set skip_chroma !!\n" ); ++ else ++ printf( "vo_vdpau: skip_chroma = %d\n", this_gen->skip_chroma ); ++} ++ ++ ++ ++static void vdpau_set_skip_chroma( void *this_gen, xine_cfg_entry_t *entry ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ this->skip_chroma = entry->num_value; ++ vdpau_update_skip_chroma( this ); ++} ++ ++ ++ ++static void vdpau_shift_queue( vo_driver_t *this_gen ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ pthread_mutex_lock(&this->queue_lock); ++ if ( this->init_queue < this->queue_length ) ++ ++this->init_queue; ++ ++this->current_output_surface; ++ if ( this->current_output_surface >= this->queue_length ) ++ this->current_output_surface = 0; ++ pthread_mutex_unlock(&this->queue_lock); ++ pthread_cond_broadcast(&this->queue_changed); ++} ++ ++ ++ ++static void vdpau_check_output_size( vo_driver_t *this_gen ) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { ++ /* recreate output surface to match window size */ ++ lprintf( "vo_vdpau: output_surface size update\n" ); ++ this->output_surface_width[this->current_output_surface] = this->sc.gui_width; ++ this->output_surface_height[this->current_output_surface] = this->sc.gui_height; ++ ++ vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); ++ vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); ++ } ++} ++ ++ ++ ++static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; ++ VdpStatus st; ++ VdpVideoSurface surface; ++ VdpChromaType chroma = this->video_mixer_chroma; ++ VdpColorStandard color_standard = this->color_standard; ++ uint32_t mix_w = this->video_mixer_width; ++ uint32_t mix_h = this->video_mixer_height; ++ VdpTime stream_speed; ++ ++ if(this->reinit_needed) ++ vdpau_reinit(this_gen); ++ ++ if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) { ++ this->sc.force_redraw = 1; /* trigger re-calc of output size */ ++ } ++ ++ this->sc.delivered_height = frame->height; ++ this->sc.delivered_width = frame->width; ++ this->sc.delivered_ratio = frame->ratio; ++ this->sc.crop_left = frame->vo_frame.crop_left; ++ this->sc.crop_right = frame->vo_frame.crop_right; ++ this->sc.crop_top = frame->vo_frame.crop_top; ++ this->sc.crop_bottom = frame->vo_frame.crop_bottom; ++ ++ vdpau_redraw_needed( this_gen ); ++ ++ if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { ++ chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; ++ if ( (frame->width != this->soft_surface_width) || (frame->height != this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { ++ lprintf( "vo_vdpau: soft_surface size update\n" ); ++ /* recreate surface to match frame changes */ ++ this->soft_surface_width = frame->width; ++ this->soft_surface_height = frame->height; ++ this->soft_surface_format = frame->format; ++ vdp_video_surface_destroy( this->soft_surface ); ++ this->soft_surface = VDP_INVALID_HANDLE; ++ vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); ++ } ++ /* FIXME: have to swap U and V planes to get correct colors !! */ ++ uint32_t pitches[] = { frame->vo_frame.pitches[0], frame->vo_frame.pitches[2], frame->vo_frame.pitches[1] }; ++ void* data[] = { frame->vo_frame.base[0], frame->vo_frame.base[2], frame->vo_frame.base[1] }; ++ if ( frame->format==XINE_IMGFMT_YV12 ) { ++ st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YV12, &data, pitches ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YV12 error : %s\n", vdp_get_error_string( st ) ); ++ } ++ else { ++ st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YUYV, &data, pitches ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YUY2 error : %s\n", vdp_get_error_string( st ) ); ++ } ++ surface = this->soft_surface; ++ mix_w = this->soft_surface_width; ++ mix_h = this->soft_surface_height; ++ } ++ else if (frame->format == XINE_IMGFMT_VDPAU) { ++ surface = frame->vdpau_accel_data.surface; ++ mix_w = frame->width; ++ mix_h = frame->height; ++ chroma = (frame->vo_frame.flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; ++ color_standard = frame->vdpau_accel_data.color_standard; ++ } ++ else { ++ /* unknown format */ ++ printf( "vo_vdpau: got an unknown image -------------\n" ); ++ frame->vo_frame.free( &frame->vo_frame ); ++ return; ++ } ++ ++ if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma)) { ++ vdpau_release_back_frames( this_gen ); /* empty past frames array */ ++ lprintf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); ++ vdp_video_mixer_destroy( this->video_mixer ); ++ this->video_mixer = VDP_INVALID_HANDLE; ++ VdpVideoMixerFeature features[15]; ++ int features_count = 0; ++ if ( this->noise_reduction_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; ++ ++features_count; ++ } ++ if ( this->sharpness_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; ++ ++features_count; ++ } ++ if ( this->temporal_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; ++ ++features_count; ++ } ++ if ( this->temporal_spatial_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; ++ ++features_count; ++ } ++ if ( this->inverse_telecine_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; ++ ++features_count; ++ } ++ int i; ++#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 ++ for ( i=0; iscaling_level_max; ++i ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; ++ ++features_count; ++ } ++#endif ++ VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, ++ VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; ++ int num_layers = 3; ++ void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; ++ vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); ++ this->video_mixer_chroma = chroma; ++ this->video_mixer_width = mix_w; ++ this->video_mixer_height = mix_h; ++ vdpau_set_deinterlace( this_gen ); ++ vdpau_set_scaling_level( this_gen ); ++ vdpau_set_inverse_telecine( this_gen ); ++ vdpau_update_noise( this ); ++ vdpau_update_sharpness( this ); ++ this->color_standard = color_standard; ++ vdpau_update_csc( this ); ++ vdpau_update_skip_chroma( this ); ++ } ++ ++ if (color_standard != this->color_standard) { ++ lprintf("vo_vdpau: update color_standard: %d\n", color_standard); ++ this->color_standard = color_standard; ++ vdpau_update_csc( this ); ++ } ++ ++ VdpRect vid_source, out_dest, vid_dest; ++ vid_source.x0 = this->sc.displayed_xoffset; vid_source.y0 = this->sc.displayed_yoffset; ++ vid_source.x1 = this->sc.displayed_width+this->sc.displayed_xoffset; vid_source.y1 = this->sc.displayed_height+this->sc.displayed_yoffset; ++ out_dest.x0 = out_dest.y0 = 0; ++ out_dest.x1 = this->sc.gui_width; out_dest.y1 = this->sc.gui_height; ++ vid_dest.x0 = this->sc.output_xoffset; vid_dest.y0 = this->sc.output_yoffset; ++ vid_dest.x1 = this->sc.output_xoffset+this->sc.output_width; vid_dest.y1 = this->sc.output_yoffset+this->sc.output_height; ++ ++ /* prepare field delay calculation to not run into a deadlock while display locked */ ++ stream_speed = frame->vo_frame.stream ? xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) : 0; ++ if (stream_speed != 0) { ++ int vo_bufs_in_fifo = 0; ++ _x_query_buffer_usage(frame->vo_frame.stream, NULL, NULL, &vo_bufs_in_fifo, NULL); ++ /* fprintf(stderr, "vo_bufs: %d\n", vo_bufs_in_fifo); */ ++ if (vo_bufs_in_fifo <= 0) ++ stream_speed = 0; /* still image -> no delay */ ++ } ++ ++ uint32_t layer_count = 0; ++ VdpLayer layer[2]; ++ VdpRect ovl_source, unscaled_source; ++ if ( this->has_overlay ) { ++ ovl_source.x0 = 0; ovl_source.y0 = 0; ovl_source.x1 = this->overlay_output_width; ovl_source.y1 = this->overlay_output_height; ++ layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &ovl_source; layer[0].destination_rect = &vid_dest; ++ /* recalculate video destination window to match osd's specified video window */ ++ if (!this->has_unscaled && this->video_window_width > 0 && this->video_window_height > 0) { ++ VdpRect win_rect = { this->video_window_x, this->video_window_y, this->video_window_x + this->video_window_width, this->video_window_y + this->video_window_height }; ++ vid_dest.x0 = ((win_rect.x0 - ovl_source.x0) * (vid_dest.x1 - vid_dest.x0) + vid_dest.x0 * (ovl_source.x1 - ovl_source.x0)) / (ovl_source.x1 - ovl_source.x0); ++ vid_dest.y0 = ((win_rect.y0 - ovl_source.y0) * (vid_dest.y1 - vid_dest.y0) + vid_dest.y0 * (ovl_source.y1 - ovl_source.y0)) / (ovl_source.y1 - ovl_source.y0); ++ vid_dest.x1 = ((win_rect.x1 - ovl_source.x0) * (vid_dest.x1 - vid_dest.x0) + vid_dest.x0 * (ovl_source.x1 - ovl_source.x0)) / (ovl_source.x1 - ovl_source.x0); ++ vid_dest.y1 = ((win_rect.y1 - ovl_source.y0) * (vid_dest.y1 - vid_dest.y0) + vid_dest.y0 * (ovl_source.y1 - ovl_source.y0)) / (ovl_source.y1 - ovl_source.y0); ++ } ++ ++layer_count; ++ } ++ ++ if ( this->has_unscaled ) { ++ unscaled_source.x0 = 0; unscaled_source.y0 = 0; unscaled_source.x1 = this->overlay_unscaled_width; unscaled_source.y1 = this->overlay_unscaled_height; ++ layer[layer_count].struct_version = VDP_LAYER_VERSION; layer[layer_count].source_surface = this->overlay_unscaled; layer[layer_count].source_rect = &unscaled_source; layer[layer_count].destination_rect = &unscaled_source; ++ /* recalculate video destination window to match osd's specified video window */ ++ if (this->video_window_width > 0 && this->video_window_height > 0) { ++ vid_dest.x0 = this->video_window_x; ++ vid_dest.y0 = this->video_window_y; ++ vid_dest.x1 = this->video_window_x + this->video_window_width; ++ vid_dest.y1 = this->video_window_y + this->video_window_height; ++ } ++ ++layer_count; ++ } ++ ++ /* try to get frame duration from previous img->pts when frame->duration is 0 */ ++ int frame_duration = frame->vo_frame.duration; ++ if ( !frame_duration && this->back_frame[0] ) { ++ int duration = frame->vo_frame.pts - this->back_frame[0]->vo_frame.pts; ++ if ( duration>0 && duration<4000 ) ++ frame_duration = duration; ++ } ++ int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; ++ ++ VdpTime last_time; ++ ++ if ( this->init_queue>=this->queue_length ) ++ vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); ++ ++#ifdef LOCKDISPLAY ++ XLockDisplay( this->display ); ++#endif ++ ++ pthread_mutex_lock(&this->output_surface_lock[this->current_output_surface]); ++ this->output_surface_vpts[this->current_output_surface] = frame->vo_frame.vpts; ++ ++ vdpau_check_output_size( this_gen ); ++ ++ if ( frame->format==XINE_IMGFMT_VDPAU && this->deinterlace && non_progressive /*&& stream_speed*/ && frame_duration>2500 ) { ++ VdpTime current_time = 0; ++ VdpVideoSurface past[2]; ++ VdpVideoSurface future[1]; ++ VdpVideoMixerPictureStructure picture_structure; ++ ++ past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; ++ future[0] = surface; ++ picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; ++ ++ st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, ++ 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); ++ ++ pthread_mutex_unlock(&this->output_surface_lock[this->current_output_surface]); ++ ++ vdp_queue_get_time( vdp_queue, ¤t_time ); ++ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); /* display _now_ */ ++ vdpau_shift_queue( this_gen ); ++ ++ int dm = this->deinterlacers_method[this->deinterlace_method]; ++ if ( (dm != DEINT_HALF_TEMPORAL) && (dm != DEINT_HALF_TEMPORAL_SPATIAL) && frame->vo_frame.future_frame ) { /* process second field */ ++ if ( this->init_queue>=this->queue_length ) { ++#ifdef LOCKDISPLAY ++ XUnlockDisplay(this->display); ++#endif ++ vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); ++#ifdef LOCKDISPLAY ++ XLockDisplay(this->display); ++#endif ++ } ++ ++ pthread_mutex_lock(&this->output_surface_lock[this->current_output_surface]); ++ this->output_surface_vpts[this->current_output_surface] = frame->vo_frame.vpts; ++ if (stream_speed > 0) ++ this->output_surface_vpts[this->current_output_surface] += (uint64_t)frame->vo_frame.duration * XINE_FINE_SPEED_NORMAL / (2 * stream_speed); ++ ++ vdpau_check_output_size( this_gen ); ++ ++ picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; ++ past[0] = surface; ++ if ( frame->vo_frame.future_frame!=NULL && ((vdpau_frame_t*)(frame->vo_frame.future_frame))->format==XINE_IMGFMT_VDPAU ) ++ future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; ++ else ++ future[0] = VDP_INVALID_HANDLE; ++ ++ st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, ++ 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); ++ ++ pthread_mutex_unlock(&this->output_surface_lock[this->current_output_surface]); ++ ++ /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ ++ if (stream_speed > 0) ++ current_time += frame->vo_frame.duration * 1000000ull * XINE_FINE_SPEED_NORMAL / (180 * stream_speed); ++ else ++ current_time = 0; /* immediately i. e. no delay */ ++ ++ //current_time = 0; ++ //printf( "vo_vdpau: deint delay = %d\n", frame_duration *1ull * XINE_FINE_SPEED_NORMAL / (180 * stream_speed) ); ++ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); ++ vdpau_shift_queue( this_gen ); ++ } ++ } ++ else { ++ st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, ++ 0, 0, surface, 0, 0, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); ++ ++ pthread_mutex_unlock(&this->output_surface_lock[this->current_output_surface]); ++ ++ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); ++ vdpau_shift_queue( this_gen ); ++ } ++ ++#ifdef LOCKDISPLAY ++ XUnlockDisplay( this->display ); ++#endif ++ ++ if ( stream_speed ) /* do not release past frame if paused, it will be used for redrawing */ ++ vdpau_backup_frame( this_gen, frame_gen ); ++ else ++ frame->vo_frame.free( &frame->vo_frame ); ++} ++ ++ ++ ++static int vdpau_get_property (vo_driver_t *this_gen, int property) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t*)this_gen; ++ ++ switch (property) { ++ case VO_PROP_MAX_NUM_FRAMES: ++ return 30; ++ case VO_PROP_WINDOW_WIDTH: ++ return this->sc.gui_width; ++ case VO_PROP_WINDOW_HEIGHT: ++ return this->sc.gui_height; ++ case VO_PROP_OUTPUT_WIDTH: ++ return this->sc.output_width; ++ case VO_PROP_OUTPUT_HEIGHT: ++ return this->sc.output_height; ++ case VO_PROP_OUTPUT_XOFFSET: ++ return this->sc.output_xoffset; ++ case VO_PROP_OUTPUT_YOFFSET: ++ return this->sc.output_yoffset; ++ case VO_PROP_HUE: ++ return this->hue; ++ case VO_PROP_SATURATION: ++ return this->saturation; ++ case VO_PROP_CONTRAST: ++ return this->contrast; ++ case VO_PROP_BRIGHTNESS: ++ return this->brightness; ++ case VO_PROP_SHARPNESS: ++ return this->sharpness; ++ case VO_PROP_NOISE_REDUCTION: ++ return this->noise; ++ case VO_PROP_ZOOM_X: ++ return this->zoom_x; ++ case VO_PROP_ZOOM_Y: ++ return this->zoom_y; ++ case VO_PROP_ASPECT_RATIO: ++ return this->sc.user_ratio; ++ } ++ ++ return -1; ++} ++ ++ ++ ++static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t*)this_gen; ++ ++ printf("vdpau_set_property: property=%d, value=%d\n", property, value ); ++ ++ switch (property) { ++ case VO_PROP_INTERLACED: ++ this->deinterlace = value; ++ vdpau_set_deinterlace( this_gen ); ++ break; ++ case VO_PROP_ZOOM_X: ++ if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { ++ this->zoom_x = value; ++ this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; ++ _x_vo_scale_compute_ideal_size( &this->sc ); ++ this->sc.force_redraw = 1; /* trigger re-calc of output size */ ++ } ++ break; ++ case VO_PROP_ZOOM_Y: ++ if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { ++ this->zoom_y = value; ++ this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; ++ _x_vo_scale_compute_ideal_size( &this->sc ); ++ this->sc.force_redraw = 1; /* trigger re-calc of output size */ ++ } ++ break; ++ case VO_PROP_ASPECT_RATIO: ++ if ( value>=XINE_VO_ASPECT_NUM_RATIOS ) ++ value = XINE_VO_ASPECT_AUTO; ++ this->sc.user_ratio = value; ++ this->sc.force_redraw = 1; /* trigger re-calc of output size */ ++ break; ++ case VO_PROP_HUE: this->hue = value; vdpau_update_csc( this ); break; ++ case VO_PROP_SATURATION: this->saturation = value; vdpau_update_csc( this ); break; ++ case VO_PROP_CONTRAST: this->contrast = value; vdpau_update_csc( this ); break; ++ case VO_PROP_BRIGHTNESS: this->brightness = value; vdpau_update_csc( this ); break; ++ case VO_PROP_SHARPNESS: this->sharpness = value; vdpau_update_sharpness( this ); break; ++ case VO_PROP_NOISE_REDUCTION: this->noise = value; vdpau_update_noise( this ); break; ++ } ++ ++ return value; ++} ++ ++ ++ ++static void vdpau_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) ++{ ++ switch ( property ) { ++ case VO_PROP_HUE: ++ *max = 314; *min = -314; break; ++ case VO_PROP_SATURATION: ++ *max = 1000; *min = 0; break; ++ case VO_PROP_CONTRAST: ++ *max = 1000; *min = 0; break; ++ case VO_PROP_BRIGHTNESS: ++ *max = 100; *min = -100; break; ++ case VO_PROP_SHARPNESS: ++ *max = 100; *min = -100; break; ++ case VO_PROP_NOISE_REDUCTION: ++ *max = 100; *min = 0; break; ++ default: ++ *max = 0; *min = 0; ++ } ++} ++ ++ ++typedef struct { ++ xine_grab_frame_t grab_frame; ++ ++ VdpOutputSurface render_surface; ++ int vdp_runtime_nr; ++ int width, height; ++ uint32_t *rgba; ++} vdpau_grab_frame_t; ++ ++ ++static int vdpau_alloc_grab_frame(vdpau_driver_t *this, void *data) ++{ ++ vdpau_grab_frame_t *frame = calloc(1, sizeof(vdpau_grab_frame_t)); ++ if (!frame) ++ return -1; ++ ++ frame->render_surface = VDP_INVALID_HANDLE; ++ frame->grab_frame.vpts = -1; ++ *((vdpau_grab_frame_t **) data) = frame; ++ ++ return 0; ++} ++ ++ ++static int vdpau_free_grab_frame(vdpau_driver_t *this, void *data) ++{ ++ vdpau_grab_frame_t *frame = (vdpau_grab_frame_t *) data; ++ ++ free(frame->grab_frame.img); ++ free(frame->rgba); ++ if (frame->render_surface != VDP_INVALID_HANDLE && frame->vdp_runtime_nr == this->vdp_runtime_nr) { ++ if (vdp_output_surface_destroy(frame->render_surface) != VDP_STATUS_OK) ++ printf("vo_vdpau: Can't destroy output surface!\n"); ++ } ++ free(frame); ++ return 0; ++} ++ ++ ++static int vdpau_grab_last_displayed_frame (vdpau_driver_t *this, void *data) { ++ vdpau_grab_frame_t *frame = (vdpau_grab_frame_t *) data; ++ int previous = -1; ++ ++ pthread_mutex_lock(&this->queue_lock); ++ if (this->init_queue) { ++ previous = this->current_output_surface ? this->current_output_surface - 1: this->queue_length - 1; ++ ++ /* Ensure that we do not grab the same frame again */ ++ if (frame->grab_frame.vpts == this->output_surface_vpts[previous]) ++ previous = -1; ++ } ++ if (previous == -1 && frame->grab_frame.timeout > 0) { ++ /* wait for next displayed frame */ ++ struct timeval tvnow, tvdiff, tvtimeout; ++ struct timespec ts; ++ tvdiff.tv_sec = frame->grab_frame.timeout / 1000; ++ tvdiff.tv_usec = frame->grab_frame.timeout % 1000; ++ tvdiff.tv_usec *= 1000; ++ gettimeofday(&tvnow, NULL); ++ timeradd(&tvnow, &tvdiff, &tvtimeout); ++ ts.tv_sec = tvtimeout.tv_sec; ++ ts.tv_nsec = tvtimeout.tv_usec; ++ ts.tv_nsec *= 1000; ++ if (!pthread_cond_timedwait(&this->queue_changed, &this->queue_lock, &ts)) ++ previous = this->current_output_surface ? this->current_output_surface - 1: this->queue_length - 1; ++ } ++ pthread_mutex_unlock(&this->queue_lock); ++ ++ if (previous == -1) ++ return 1; /* no frame available */ ++ ++ pthread_mutex_lock(&this->output_surface_lock[previous]); ++ ++ int width = this->output_surface_width[previous] - frame->grab_frame.crop_left - frame->grab_frame.crop_right; ++ int height = this->output_surface_height[previous] - frame->grab_frame.crop_top - frame->grab_frame.crop_bottom; ++ if (width < 1) ++ width = 1; ++ if (height < 1) ++ height = 1; ++ ++ if (frame->grab_frame.width <= 0) ++ frame->grab_frame.width = width; ++ if (frame->grab_frame.height <= 0) ++ frame->grab_frame.height = height; ++ ++ if (frame->vdp_runtime_nr != this->vdp_runtime_nr) ++ frame->render_surface = VDP_INVALID_HANDLE; ++ ++ if (frame->grab_frame.width != frame->width || frame->grab_frame.height != frame->height) { ++ free(frame->rgba); ++ free(frame->grab_frame.img); ++ frame->rgba = NULL; ++ frame->grab_frame.img = NULL; ++ ++ if (frame->render_surface != VDP_INVALID_HANDLE) { ++ if (vdp_output_surface_destroy(frame->render_surface) != VDP_STATUS_OK) ++ printf("vo_vdpau: Can't destroy output surface!\n"); ++ frame->render_surface = VDP_INVALID_HANDLE; ++ } ++ ++ frame->width = frame->grab_frame.width; ++ frame->height = frame->grab_frame.height; ++ } ++ ++ if (frame->rgba == NULL) { ++ frame->rgba = (uint32_t *) calloc(frame->width * frame->height, sizeof(uint32_t)); ++ if (frame->rgba == NULL) ++ return -1; ++ frame->grab_frame.img = (uint8_t *) calloc(frame->width * frame->height, 3); ++ if (frame->grab_frame.img == NULL) ++ return -1; ++ } ++ ++ VdpStatus st; ++ uint32_t pitches = frame->width * sizeof(uint32_t); ++ VdpRect src_rect = { frame->grab_frame.crop_left, frame->grab_frame.crop_top, width+frame->grab_frame.crop_left, height+frame->grab_frame.crop_top }; ++ frame->grab_frame.vpts = this->output_surface_vpts[previous]; ++ ++ if (frame->width != width || frame->height != height) { ++ st = VDP_STATUS_OK; ++ if (frame->render_surface == VDP_INVALID_HANDLE) { ++ frame->vdp_runtime_nr = this->vdp_runtime_nr; ++ st = vdp_output_surface_create(vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, frame->width, frame->height, &frame->render_surface); ++ } ++ if (st == VDP_STATUS_OK) { ++ st = vdp_output_surface_render_output_surface(frame->render_surface, NULL, this->output_surface[previous], &src_rect, NULL, NULL, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); ++ pthread_mutex_unlock(&this->output_surface_lock[previous]); ++ if (st == VDP_STATUS_OK) { ++ st = vdp_output_surface_get_bits(frame->render_surface, NULL, &frame->rgba, &pitches); ++ if (st != VDP_STATUS_OK) ++ printf("vo_vdpau: Can't get output surface bits for raw frame grabbing!\n"); ++ } ++ else ++ printf("vo_vdpau: Can't render output surface for raw frame grabbing!\n"); ++ } else { ++ pthread_mutex_unlock(&this->output_surface_lock[previous]); ++ printf("vo_vdpau: Can't create output surface for raw frame grabbing!\n"); ++ } ++ } else { ++ st = vdp_output_surface_get_bits(this->output_surface[previous], &src_rect, &frame->rgba, &pitches); ++ pthread_mutex_unlock(&this->output_surface_lock[previous]); ++ if (st != VDP_STATUS_OK) ++ printf("vo_vdpau: Can't get output surface bits for raw frame grabbing!\n"); ++ } ++ if (st == VDP_STATUS_OK) { ++ uint32_t *src = frame->rgba; ++ uint8_t *dst = frame->grab_frame.img; ++ int n = frame->width * frame->height; ++ while (n--) { ++ *dst++ = (uint8_t)(*src >> 16); /*R*/ ++ *dst++ = (uint8_t)(*src >> 8); /*G*/ ++ *dst++ = (uint8_t)(*src++); /*B*/ ++ } ++ return 0; ++ } ++ ++ frame->grab_frame.vpts = -1; ++ return -1; ++} ++ ++ ++static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t*)this_gen; ++ ++ switch (data_type) { ++#ifndef XINE_DISABLE_DEPRECATED_FEATURES ++ case XINE_GUI_SEND_COMPLETION_EVENT: ++ break; ++#endif ++ ++ case XINE_GUI_SEND_EXPOSE_EVENT: { ++ if ( this->init_queue ) { ++#ifdef LOCKDISPLAY ++ XLockDisplay( this->display ); ++#endif ++ int previous = this->current_output_surface ? this->current_output_surface - 1: this->queue_length - 1; ++ vdp_queue_display( vdp_queue, this->output_surface[previous], 0, 0, 0 ); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay( this->display ); ++#endif ++ } ++ break; ++ } ++ ++ case XINE_GUI_SEND_DRAWABLE_CHANGED: { ++ VdpStatus st; ++#ifdef LOCKDISPLAY ++ XLockDisplay( this->display ); ++#endif ++ this->drawable = (Drawable) data; ++ vdp_queue_destroy( vdp_queue ); ++ vdp_queue_target_destroy( vdp_queue_target ); ++ st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vo_vdpau: FATAL !! Can't recreate presentation queue target after drawable change !!\n" ); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay( this->display ); ++#endif ++ break; ++ } ++ st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vo_vdpau: FATAL !! Can't recreate presentation queue after drawable change !!\n" ); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay( this->display ); ++#endif ++ break; ++ } ++ vdp_queue_set_background_color( vdp_queue, &this->back_color ); ++#ifdef LOCKDISPLAY ++ XUnlockDisplay( this->display ); ++#endif ++ this->sc.force_redraw = 1; ++ break; ++ } ++ ++ case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: { ++ int x1, y1, x2, y2; ++ x11_rectangle_t *rect = data; ++ ++ _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, &x1, &y1); ++ _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, &x2, &y2); ++ rect->x = x1; ++ rect->y = y1; ++ rect->w = x2-x1; ++ rect->h = y2-y1; ++ break; ++ } ++ ++ case XINE_GUI_SEND_ALLOC_GRAB_FRAME: ++ return vdpau_alloc_grab_frame (this, data); ++ ++ case XINE_GUI_SEND_FREE_GRAB_FRAME: ++ return vdpau_free_grab_frame (this, data); ++ ++ case XINE_GUI_SEND_GRAB_FRAME: ++ return vdpau_grab_last_displayed_frame (this, data); ++ ++ default: ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++ ++static uint32_t vdpau_get_capabilities (vo_driver_t *this_gen) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ ++ return this->capabilities; ++} ++ ++ ++ ++static void vdpau_dispose (vo_driver_t *this_gen) ++{ ++ vdpau_driver_t *this = (vdpau_driver_t *) this_gen; ++ int i; ++ ++ this->ovl_yuv2rgb->dispose(this->ovl_yuv2rgb); ++ this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); ++ ++ for ( i=0; ioverlays[i].ovl_bitmap != VDP_INVALID_HANDLE ) ++ vdp_bitmap_destroy( this->overlays[i].ovl_bitmap ); ++ } ++ ++ if ( this->video_mixer!=VDP_INVALID_HANDLE ) ++ vdp_video_mixer_destroy( this->video_mixer ); ++ if ( this->soft_surface != VDP_INVALID_HANDLE ) ++ vdp_video_surface_destroy( this->soft_surface ); ++ ++ if ( vdp_output_surface_destroy ) { ++ if ( this->overlay_unscaled!=VDP_INVALID_HANDLE ) ++ vdp_output_surface_destroy( this->overlay_unscaled ); ++ if ( this->overlay_output!=VDP_INVALID_HANDLE ) ++ vdp_output_surface_destroy( this->overlay_output ); ++ for ( i=0; iqueue_length; ++i ) { ++ if ( this->output_surface[i]!=VDP_INVALID_HANDLE ) ++ vdp_output_surface_destroy( this->output_surface[i] ); ++ } ++ } ++ ++ if ( vdp_queue != VDP_INVALID_HANDLE ) ++ vdp_queue_destroy( vdp_queue ); ++ if ( vdp_queue_target != VDP_INVALID_HANDLE ) ++ vdp_queue_target_destroy( vdp_queue_target ); ++ ++ for ( i=0; iback_frame[i] ) ++ this->back_frame[i]->vo_frame.dispose( &this->back_frame[i]->vo_frame ); ++ ++ if ( (vdp_device != VDP_INVALID_HANDLE) && vdp_device_destroy ) ++ vdp_device_destroy( vdp_device ); ++ ++ for (i = 0; i < this->queue_length; ++i) ++ pthread_mutex_destroy(&this->output_surface_lock[i]); ++ pthread_mutex_destroy(&this->queue_lock); ++ pthread_cond_destroy(&this->queue_changed); ++ ++ free (this); ++} ++ ++ ++ ++static int vdpau_reinit_error( VdpStatus st, const char *msg ) ++{ ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vo_vdpau: %s : %s\n", msg, vdp_get_error_string( st ) ); ++ return 1; ++ } ++ return 0; ++} ++ ++ ++ ++static void vdpau_reinit( vo_driver_t *this_gen ) ++{ ++ printf("vo_vdpau: VDPAU was pre-empted. Reinit.\n"); ++ vdpau_driver_t *this = (vdpau_driver_t *)this_gen; ++ ++#ifdef LOCKDISPLAY ++ XLockDisplay(guarded_display); ++#endif ++ vdpau_release_back_frames(this_gen); ++ ++ VdpStatus st = vdp_device_create_x11( this->display, this->screen, &vdp_device, &vdp_get_proc_address ); ++ ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vo_vdpau: Can't create vdp device : " ); ++ if ( st == VDP_STATUS_NO_IMPLEMENTATION ) ++ printf( "No vdpau implementation.\n" ); ++ else ++ printf( "unsupported GPU?\n" ); ++ return; ++ } ++ ++ st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); ++ if ( vdpau_reinit_error( st, "Can't create presentation queue target !!" ) ) ++ return; ++ st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); ++ if ( vdpau_reinit_error( st, "Can't create presentation queue !!" ) ) ++ return; ++ vdp_queue_set_background_color( vdp_queue, &this->back_color ); ++ ++ ++ VdpChromaType chroma = VDP_CHROMA_TYPE_420; ++ st = orig_vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); ++ if ( vdpau_reinit_error( st, "Can't create video surface !!" ) ) ++ return; ++ ++ this->current_output_surface = 0; ++ this->init_queue = 0; ++ int i; ++ for ( i=0; iqueue_length; ++i ) { ++ st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[i], this->output_surface_height[i], &this->output_surface[i] ); ++ if ( vdpau_reinit_error( st, "Can't create output surface !!" ) ) { ++ int j; ++ for ( j=0; joutput_surface[j] ); ++ vdp_video_surface_destroy( this->soft_surface ); ++ return; ++ } ++ } ++ ++ /* osd overlays need to be recreated */ ++ for ( i=0; ioverlays[i].ovl_bitmap = VDP_INVALID_HANDLE; ++ this->overlays[i].bitmap_width = 0; ++ this->overlays[i].bitmap_height = 0; ++ } ++ this->overlay_output = VDP_INVALID_HANDLE; ++ this->overlay_output_width = this->overlay_output_height = 0; ++ this->overlay_unscaled = VDP_INVALID_HANDLE; ++ this->overlay_unscaled_width = this->overlay_unscaled_height = 0; ++ this->ovl_changed = 0; ++ this->has_overlay = 0; ++ this->has_unscaled = 0; ++ ++ VdpVideoMixerFeature features[15]; ++ int features_count = 0; ++ if ( this->noise_reduction_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; ++ ++features_count; ++ } ++ if ( this->sharpness_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; ++ ++features_count; ++ } ++ if ( this->temporal_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; ++ ++features_count; ++ } ++ if ( this->temporal_spatial_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; ++ ++features_count; ++ } ++ if ( this->inverse_telecine_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; ++ ++features_count; ++ } ++#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 ++ for ( i=0; iscaling_level_max; ++i ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; ++ ++features_count; ++ } ++#endif ++ VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; ++ int num_layers = 3; ++ void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; ++ st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); ++ if ( vdpau_reinit_error( st, "Can't create video mixer !!" ) ) { ++ orig_vdp_video_surface_destroy( this->soft_surface ); ++ for ( i=0; iqueue_length; ++i ) ++ vdp_output_surface_destroy( this->output_surface[i] ); ++ return; ++ } ++ this->video_mixer_chroma = chroma; ++ vdpau_set_deinterlace( this_gen ); ++ vdpau_set_scaling_level( this_gen ); ++ vdpau_set_inverse_telecine( this_gen ); ++ vdpau_update_noise( this ); ++ vdpau_update_sharpness( this ); ++ vdpau_update_csc( this ); ++ vdpau_update_skip_chroma( this ); ++ ++ vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); ++ ++ this->vdp_runtime_nr++; ++ this->reinit_needed = 0; ++#ifdef LOCKDISPLAY ++ XUnlockDisplay(guarded_display); ++#endif ++ printf("vo_vdpau: Reinit done.\n"); ++} ++ ++ ++ ++static void vdp_preemption_callback(VdpDevice device, void *context) ++{ ++ printf("vo_vdpau: VDPAU preemption callback\n"); ++ vdpau_driver_t *this = (vdpau_driver_t *)context; ++ this->reinit_needed = 1; ++} ++ ++ ++ ++static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, int error_string ) ++{ ++ if ( st != VDP_STATUS_OK ) { ++ if ( error_string ) ++ printf( "vo_vdpau: %s : %s\n", msg, vdp_get_error_string( st ) ); ++ else ++ printf( "vo_vdpau: %s\n", msg ); ++ vdpau_dispose( driver ); ++ return 1; ++ } ++ return 0; ++} ++ ++ ++ ++static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) ++{ ++ vdpau_class_t *class = (vdpau_class_t *) class_gen; ++ x11_visual_t *visual = (x11_visual_t *) visual_gen; ++ vdpau_driver_t *this; ++ config_values_t *config = class->xine->config; ++ int i; ++ ++ this = (vdpau_driver_t *) calloc(1, sizeof(vdpau_driver_t)); ++ ++ if (!this) ++ return NULL; ++ ++ guarded_display = visual->display; ++ this->display = visual->display; ++ this->screen = visual->screen; ++ this->drawable = visual->d; ++ ++ _x_vo_scale_init(&this->sc, 1, 0, config); ++ this->sc.frame_output_cb = visual->frame_output_cb; ++ this->sc.dest_size_cb = visual->dest_size_cb; ++ this->sc.user_data = visual->user_data; ++ this->sc.user_ratio = XINE_VO_ASPECT_AUTO; ++ ++ this->zoom_x = 100; ++ this->zoom_y = 100; ++ ++ this->xine = class->xine; ++ this->config = config; ++ ++ this->vo_driver.get_capabilities = vdpau_get_capabilities; ++ this->vo_driver.alloc_frame = vdpau_alloc_frame; ++ this->vo_driver.update_frame_format = vdpau_update_frame_format; ++ this->vo_driver.overlay_begin = vdpau_overlay_begin; ++ this->vo_driver.overlay_blend = vdpau_overlay_blend; ++ this->vo_driver.overlay_end = vdpau_overlay_end; ++ this->vo_driver.display_frame = vdpau_display_frame; ++ this->vo_driver.get_property = vdpau_get_property; ++ this->vo_driver.set_property = vdpau_set_property; ++ this->vo_driver.get_property_min_max = vdpau_get_property_min_max; ++ this->vo_driver.gui_data_exchange = vdpau_gui_data_exchange; ++ this->vo_driver.dispose = vdpau_dispose; ++ this->vo_driver.redraw_needed = vdpau_redraw_needed; ++ ++ this->video_mixer = VDP_INVALID_HANDLE; ++ for ( i=0; ioutput_surface[i] = VDP_INVALID_HANDLE; ++ this->soft_surface = VDP_INVALID_HANDLE; ++ vdp_queue = VDP_INVALID_HANDLE; ++ vdp_queue_target = VDP_INVALID_HANDLE; ++ vdp_device = VDP_INVALID_HANDLE; ++ ++ vdp_output_surface_destroy = NULL; ++ vdp_device_destroy = NULL; ++ ++ this->sharpness_is_supported = 0; ++ this->noise_reduction_is_supported = 0; ++ this->temporal_is_supported = 0; ++ this->temporal_spatial_is_supported = 0; ++ this->inverse_telecine_is_supported = 0; ++ this->skip_chroma_is_supported = 0; ++ ++ for ( i=0; ioverlays[i].ovl_w = this->overlays[i].ovl_h = 0; ++ this->overlays[i].bitmap_width = this->overlays[i].bitmap_height = 0; ++ this->overlays[i].ovl_bitmap = VDP_INVALID_HANDLE; ++ this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0; ++ } ++ this->overlay_output = VDP_INVALID_HANDLE; ++ this->overlay_output_width = this->overlay_output_height = 0; ++ this->overlay_unscaled = VDP_INVALID_HANDLE; ++ this->overlay_unscaled_width = this->overlay_unscaled_height = 0; ++ this->ovl_changed = 0; ++ this->has_overlay = 0; ++ this->has_unscaled = 0; ++ ++ /* overlay converter */ ++ this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); ++ this->ovl_yuv2rgb = this->yuv2rgb_factory->create_converter( this->yuv2rgb_factory ); ++ ++ VdpStatus st = vdp_device_create_x11( visual->display, visual->screen, &vdp_device, &vdp_get_proc_address ); ++ if ( st != VDP_STATUS_OK ) { ++ printf( "vo_vdpau: Can't create vdp device : " ); ++ if ( st == VDP_STATUS_NO_IMPLEMENTATION ) ++ printf( "No vdpau implementation.\n" ); ++ else ++ printf( "unsupported GPU?\n" ); ++ vdpau_dispose( &this->vo_driver ); ++ return NULL; ++ } ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_ERROR_STRING , (void*)&vdp_get_error_string ); ++ if ( vdpau_init_error( st, "Can't get GET_ERROR_STRING proc address !!", &this->vo_driver, 0 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_API_VERSION , (void*)&vdp_get_api_version ); ++ if ( vdpau_init_error( st, "Can't get GET_API_VERSION proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ uint32_t tmp; ++ vdp_get_api_version( &tmp ); ++ printf( "vo_vdpau: vdpau API version : %d\n", tmp ); ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_INFORMATION_STRING , (void*)&vdp_get_information_string ); ++ if ( vdpau_init_error( st, "Can't get GET_INFORMATION_STRING proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ const char *s; ++ st = vdp_get_information_string( &s ); ++ printf( "vo_vdpau: vdpau implementation description : %s\n", s ); ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES , (void*)&vdp_video_surface_query_get_put_bits_ycbcr_capabilities ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ VdpBool ok; ++ st = vdp_video_surface_query_get_put_bits_ycbcr_capabilities( vdp_device, VDP_CHROMA_TYPE_422, VDP_YCBCR_FORMAT_YUYV, &ok ); ++ if ( vdpau_init_error( st, "Failed to check vdpau yuy2 capability", &this->vo_driver, 1 ) ) ++ return NULL; ++ if ( !ok ) { ++ printf( "vo_vdpau: VideoSurface doesn't support yuy2, sorry.\n"); ++ vdpau_dispose( &this->vo_driver ); ++ return NULL; ++ } ++ st = vdp_video_surface_query_get_put_bits_ycbcr_capabilities( vdp_device, VDP_CHROMA_TYPE_420, VDP_YCBCR_FORMAT_YV12, &ok ); ++ if ( vdpau_init_error( st, "Failed to check vdpau yv12 capability", &this->vo_driver, 1 ) ) ++ return NULL; ++ if ( !ok ) { ++ printf( "vo_vdpau: VideoSurface doesn't support yv12, sorry.\n"); ++ vdpau_dispose( &this->vo_driver ); ++ return NULL; ++ } ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DEVICE_DESTROY , (void*)&vdp_device_destroy ); ++ if ( vdpau_init_error( st, "Can't get DEVICE_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void*)&orig_vdp_video_surface_create ); vdp_video_surface_create = guarded_vdp_video_surface_create; ++ if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , (void*)&orig_vdp_video_surface_destroy ); vdp_video_surface_destroy = guarded_vdp_video_surface_destroy; ++ if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_video_surface_putbits_ycbcr ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_PUT_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , (void*)&vdp_video_surface_getbits_ycbcr ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_GET_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void*)&vdp_output_surface_create ); ++ if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , (void*)&vdp_output_surface_destroy ); ++ if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE , (void*)&vdp_output_surface_render_bitmap_surface ); ++ if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_RENDER_BITMAP_SURFACE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE , (void*)&vdp_output_surface_render_output_surface ); ++ if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_output_surface_put_bits ); ++ if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE , (void*)&vdp_output_surface_get_bits ); ++ if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_CREATE , (void*)&vdp_video_mixer_create ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_CREATE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_DESTROY , (void*)&vdp_video_mixer_destroy ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_RENDER , (void*)&vdp_video_mixer_render ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_RENDER proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , (void*)&vdp_video_mixer_set_attribute_values ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_SET_ATTRIBUTE_VALUES proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES , (void*)&vdp_video_mixer_set_feature_enables ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_SET_FEATURE_ENABLES proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES , (void*)&vdp_video_mixer_get_feature_enables ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_GET_FEATURE_ENABLES proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT , (void*)&vdp_video_mixer_query_feature_support ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_FEATURE_SUPPORT proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT , (void*)&vdp_video_mixer_query_parameter_support ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_PARAMETER_SUPPORT proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT , (void*)&vdp_video_mixer_query_attribute_support ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE , (void*)&vdp_video_mixer_query_parameter_value_range ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE , (void*)&vdp_video_mixer_query_attribute_value_range ); ++ if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GENERATE_CSC_MATRIX , (void*)&vdp_generate_csc_matrix ); ++ if ( vdpau_init_error( st, "Can't get GENERATE_CSC_MATRIX proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , (void*)&vdp_queue_target_create_x11 ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_TARGET_CREATE_X11 proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , (void*)&vdp_queue_target_destroy ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_TARGET_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , (void*)&vdp_queue_create ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_CREATE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , (void*)&vdp_queue_destroy ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , (void*)&vdp_queue_display ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_DISPLAY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE , (void*)&vdp_queue_block ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR , (void*)&vdp_queue_set_background_color ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_SET_BACKGROUND_COLOR proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , (void*)&vdp_queue_get_time ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_GET_TIME proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , (void*)&vdp_queue_query_surface_status ); ++ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_QUERY_SURFACE_STATUS proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void*)&vdp_decoder_query_capabilities ); ++ if ( vdpau_init_error( st, "Can't get DECODER_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_CREATE , (void*)&orig_vdp_decoder_create ); vdp_decoder_create = guarded_vdp_decoder_create; ++ if ( vdpau_init_error( st, "Can't get DECODER_CREATE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_DESTROY , (void*)&orig_vdp_decoder_destroy ); vdp_decoder_destroy = guarded_vdp_decoder_destroy; ++ if ( vdpau_init_error( st, "Can't get DECODER_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_RENDER , (void*)&orig_vdp_decoder_render ); vdp_decoder_render = guarded_vdp_decoder_render; ++ if ( vdpau_init_error( st, "Can't get DECODER_RENDER proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_CREATE , (void*)&vdp_bitmap_create ); ++ if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_DESTROY , (void*)&vdp_bitmap_destroy ); ++ if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_bitmap_put_bits ); ++ if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, (void*)&vdp_preemption_callback_register ); ++ if ( vdpau_init_error( st, "Can't get PREEMPTION_CALLBACK_REGISTER proc address !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ ++ st = vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); ++ if ( vdpau_init_error( st, "Can't register preemption callback !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ ++ st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); ++ if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); ++ if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ ++ /* choose almost black as backcolor for color keying */ ++ this->back_color.red = 0.02; ++ this->back_color.green = 0.01; ++ this->back_color.blue = 0.03; ++ this->back_color.alpha = 1; ++ vdp_queue_set_background_color( vdp_queue, &this->back_color ); ++ ++ this->soft_surface_width = 320; ++ this->soft_surface_height = 240; ++ this->soft_surface_format = XINE_IMGFMT_YV12; ++ VdpChromaType chroma = VDP_CHROMA_TYPE_420; ++ st = vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); ++ if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) ++ return NULL; ++ ++ this->queue_length = config->register_num (config, "video.output.vdpau_display_queue_length", 2, /* default */ ++ _("default length of display queue"), ++ _("The default number of video output surfaces to create for the display queue"), ++ 20, NULL, this); ++ if (this->queue_length < 2) ++ this->queue_length = 2; ++ if (this->queue_length > NOUTPUTSURFACE) ++ this->queue_length = NOUTPUTSURFACE; ++ ++ for ( i=0; iqueue_length; ++i ) { ++ this->output_surface_width[i] = 320; ++ this->output_surface_height[i] = 240; ++ } ++ this->current_output_surface = 0; ++ this->init_queue = 0; ++ pthread_mutex_init(&this->queue_lock, NULL); ++ pthread_cond_init(&this->queue_changed, NULL); ++ ++ for ( i=0; iqueue_length; ++i ) { ++ pthread_mutex_init(&this->output_surface_lock[i], NULL); ++ st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[i], this->output_surface_height[i], &this->output_surface[i] ); ++ if ( vdpau_init_error( st, "Can't create output surface !!", &this->vo_driver, 1 ) ) { ++ int j; ++ for ( j=0; joutput_surface[j] ); ++ vdp_video_surface_destroy( this->soft_surface ); ++ return NULL; ++ } ++ } ++ ++ this->scaling_level_max = this->scaling_level_current = 0; ++#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 ++ VdpBool hqscaling; ++ for ( i=0; i<9; ++i ) { ++ st = vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i, &hqscaling ); ++ if ( ( st != VDP_STATUS_OK ) || !hqscaling ) { ++ //printf("unsupported scaling quality=%d\n", i); ++ break; ++ } ++ else { ++ //printf("supported scaling quality=%d\n", i); ++ ++this->scaling_level_max; ++ } ++ } ++#endif ++ ++ vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, &this->temporal_is_supported ); ++ vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, &this->temporal_spatial_is_supported ); ++ vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, &this->noise_reduction_is_supported ); ++ vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, &this->sharpness_is_supported ); ++ vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, &this->inverse_telecine_is_supported ); ++ vdp_video_mixer_query_attribute_support( vdp_device, VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE, &this->skip_chroma_is_supported ); ++ ++ this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; ++ this->video_mixer_chroma = chroma; ++ this->video_mixer_width = this->soft_surface_width; ++ this->video_mixer_height = this->soft_surface_height; ++ VdpVideoMixerFeature features[15]; ++ int features_count = 0; ++ if ( this->noise_reduction_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; ++ ++features_count; ++ } ++ if ( this->sharpness_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; ++ ++features_count; ++ } ++ if ( this->temporal_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; ++ ++features_count; ++ } ++ if ( this->temporal_spatial_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; ++ ++features_count; ++ } ++ if ( this->inverse_telecine_is_supported ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; ++ ++features_count; ++ } ++#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 ++ for ( i=0; iscaling_level_max; ++i ) { ++ features[features_count] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; ++ ++features_count; ++ } ++#endif ++ VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, ++ VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; ++ int num_layers = 3; ++ void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; ++ st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); ++ if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { ++ vdp_video_surface_destroy( this->soft_surface ); ++ for ( i=0; iqueue_length; ++i ) ++ vdp_output_surface_destroy( this->output_surface[i] ); ++ return NULL; ++ } ++ ++ char deinterlacers_description[1024]; ++ memset( deinterlacers_description, 0, 1024 ); ++ int deint_count = 0; ++ int deint_default = 0; ++ this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[0]; ++ this->deinterlacers_method[deint_count] = DEINT_BOB; ++ strcat( deinterlacers_description, vdpau_deinterlacer_description[0] ); ++ ++deint_count; ++ if ( this->temporal_is_supported ) { ++ this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[1]; ++ this->deinterlacers_method[deint_count] = DEINT_HALF_TEMPORAL; ++ strcat( deinterlacers_description, vdpau_deinterlacer_description[1] ); ++ ++deint_count; ++ } ++ if ( this->temporal_spatial_is_supported ) { ++ this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[2]; ++ this->deinterlacers_method[deint_count] = DEINT_HALF_TEMPORAL_SPATIAL; ++ strcat( deinterlacers_description, vdpau_deinterlacer_description[2] ); ++ ++deint_count; ++ } ++ if ( this->temporal_is_supported ) { ++ this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[3]; ++ this->deinterlacers_method[deint_count] = DEINT_TEMPORAL; ++ strcat( deinterlacers_description, vdpau_deinterlacer_description[3] ); ++ deint_default = deint_count; ++ ++deint_count; ++ } ++ if ( this->temporal_spatial_is_supported ) { ++ this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[4]; ++ this->deinterlacers_method[deint_count] = DEINT_TEMPORAL_SPATIAL; ++ strcat( deinterlacers_description, vdpau_deinterlacer_description[4] ); ++ ++deint_count; ++ } ++ this->deinterlacers_name[deint_count] = NULL; ++ ++ if ( this->scaling_level_max ) { ++ this->scaling_level_current = config->register_range( config, "video.output.vdpau_scaling_quality", 0, ++ 0, this->scaling_level_max, _("vdpau: Scaling Quality"), ++ _("Scaling Quality Level"), ++ 10, vdpau_update_scaling_level, this ); ++ } ++ ++ this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", deint_default, ++ this->deinterlacers_name, _("vdpau: HD deinterlace method"), ++ deinterlacers_description, ++ 10, vdpau_update_deinterlace_method, this ); ++ ++ if ( this->inverse_telecine_is_supported ) { ++ this->enable_inverse_telecine = config->register_bool( config, "video.output.vdpau_enable_inverse_telecine", 1, ++ _("vdpau: Try to recreate progressive frames from pulldown material"), ++ _("Enable this to detect bad-flagged progressive content to which\n" ++ "a 2:2 or 3:2 pulldown was applied.\n\n"), ++ 10, vdpau_update_enable_inverse_telecine, this ); ++ } ++ ++ this->honor_progressive = config->register_bool( config, "video.output.vdpau_honor_progressive", 0, ++ _("vdpau: disable deinterlacing when progressive_frame flag is set"), ++ _("Set to true if you want to trust the progressive_frame stream's flag.\n" ++ "This flag is not always reliable.\n\n"), ++ 10, vdpau_honor_progressive_flag, this ); ++ ++ if ( this->skip_chroma_is_supported ) { ++ this->skip_chroma = config->register_bool( config, "video.output.vdpau_skip_chroma_deinterlace", 0, ++ _("vdpau: disable advanced deinterlacers chroma filter"), ++ _("Setting to true may help if your video card isn't able to run advanced deinterlacers.\n\n"), ++ 10, vdpau_set_skip_chroma, this ); ++ } ++ ++ this->sd_only_properties = config->register_enum( config, "video.output.vdpau_sd_only_properties", 0, vdpau_sd_only_properties, ++ _("vdpau: restrict enabling video properties for SD video only"), ++ _("none\n" ++ "No restrictions\n\n" ++ "noise\n" ++ "Restrict noise reduction property.\n\n" ++ "sharpness\n" ++ "Restrict sharpness property.\n\n" ++ "noise+sharpness" ++ "Restrict noise and sharpness properties.\n\n"), ++ 10, vdpau_update_sd_only_properties, this ); ++ ++ /* number of video frames from config - register it with the default value. */ ++ int frame_num = config->register_num (config, "engine.buffers.video_num_frames", 15, /* default */ ++ _("default number of video frames"), ++ _("The default number of video frames to request " ++ "from xine video out driver. Some drivers will " ++ "override this setting with their own values."), ++ 20, NULL, this); ++ ++ /* now make sure we have at least 22 frames, to prevent ++ * locks with vdpau_h264 */ ++ if(frame_num < 22) ++ config->update_num(config,"engine.buffers.video_num_frames",22); ++ ++ this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY | VO_CAP_VIDEO_WINDOW_OVERLAY; ++ ok = 0; ++ uint32_t mw, mh, ml, mr; ++ st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_MAIN, &ok, &ml, &mr, &mw, &mh ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: getting h264_supported failed! : %s\n", vdp_get_error_string( st ) ); ++ else if ( !ok ) ++ printf( "vo_vdpau: this hardware doesn't support h264.\n" ); ++ else ++ this->capabilities |= VO_CAP_VDPAU_H264; ++ ++ st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, &ok, &ml, &mr, &mw, &mh ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: getting vc1_supported failed! : %s\n", vdp_get_error_string( st ) ); ++ else if ( !ok ) ++ printf( "vo_vdpau: this hardware doesn't support vc1.\n" ); ++ else ++ this->capabilities |= VO_CAP_VDPAU_VC1; ++ ++ st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, &ok, &ml, &mr, &mw, &mh ); ++ if ( st != VDP_STATUS_OK ) ++ printf( "vo_vdpau: getting mpeg12_supported failed! : %s\n", vdp_get_error_string( st ) ); ++ else if ( !ok ) ++ printf( "vo_vdpau: this hardware doesn't support mpeg1/2.\n" ); ++ else ++ this->capabilities |= VO_CAP_VDPAU_MPEG12; ++ ++ for ( i=0; iback_frame[i] = NULL; ++ ++ this->hue = 0; ++ this->saturation = 100; ++ this->contrast = 100; ++ this->brightness = 0; ++ this->sharpness = 0; ++ this->noise = 0; ++ this->deinterlace = 0; ++ ++ this->allocated_surfaces = 0; ++ ++ this->vdp_runtime_nr = 1; ++ ++ return &this->vo_driver; ++} ++ ++/* ++ * class functions ++ */ ++ ++static char* vdpau_get_identifier (video_driver_class_t *this_gen) ++{ ++ return "vdpau"; ++} ++ ++ ++ ++static char* vdpau_get_description (video_driver_class_t *this_gen) ++{ ++ return _("xine video output plugin using VDPAU hardware acceleration"); ++} ++ ++ ++ ++static void vdpau_dispose_class (video_driver_class_t *this_gen) ++{ ++ vdpau_class_t *this = (vdpau_class_t *) this_gen; ++ free (this); ++} ++ ++ ++ ++static void *vdpau_init_class (xine_t *xine, void *visual_gen) ++{ ++ vdpau_class_t *this = (vdpau_class_t *) calloc(1, sizeof(vdpau_class_t)); ++ ++ this->driver_class.open_plugin = vdpau_open_plugin; ++ this->driver_class.get_identifier = vdpau_get_identifier; ++ this->driver_class.get_description = vdpau_get_description; ++ this->driver_class.dispose = vdpau_dispose_class; ++ this->xine = xine; ++ ++ return this; ++} ++ ++ ++ ++static const vo_info_t vo_info_vdpau = { ++ 11, /* priority */ ++ XINE_VISUAL_TYPE_X11 /* visual type */ ++}; ++ ++ ++/* ++ * exported plugin catalog entry ++ */ ++ ++const plugin_info_t xine_plugin_info[] EXPORTED = { ++ /* type, API, "name", version, special_info, init_function */ ++ { PLUGIN_VIDEO_OUT, 21, "vdpau", XINE_VERSION_CODE, &vo_info_vdpau, vdpau_init_class }, ++ { PLUGIN_NONE, 0, "", 0, NULL, NULL } ++}; +--- xine-lib-1.1.19.orig/src/video_out/xvmc_mocomp.c ++++ xine-lib-1.1.19/src/video_out/xvmc_mocomp.c +@@ -70,9 +70,9 @@ static void xvmc_render_macro_blocks(vo_ + int second_field, + xvmc_macroblocks_t *macroblocks) { + xxmc_driver_t *this = (xxmc_driver_t *) current_image->driver; +- xxmc_frame_t *current_frame = (xxmc_frame_t *) current_image; +- xxmc_frame_t *forward_frame = (xxmc_frame_t *) forward_ref_image; +- xxmc_frame_t *backward_frame = (xxmc_frame_t *) backward_ref_image; ++ xxmc_frame_t *current_frame = XXMC_FRAME(current_image); ++ xxmc_frame_t *forward_frame = XXMC_FRAME(forward_ref_image); ++ xxmc_frame_t *backward_frame = XXMC_FRAME(backward_ref_image); + int flags; + + lprintf ("xvmc_render_macro_blocks\n"); +--- xine-lib-1.1.19.orig/src/video_out/Makefile.in ++++ xine-lib-1.1.19/src/video_out/Makefile.in +@@ -267,6 +267,22 @@ xineplug_vo_out_syncfb_la_LINK = $(LIBTO + $(LDFLAGS) -o $@ + @HAVE_SYNCFB_TRUE@@HAVE_X11_TRUE@am_xineplug_vo_out_syncfb_la_rpath = \ + @HAVE_SYNCFB_TRUE@@HAVE_X11_TRUE@ -rpath $(xineplugdir) ++xineplug_vo_out_vdpau_la_DEPENDENCIES = $(XINE_LIB) \ ++ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ ++ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) ++am_xineplug_vo_out_vdpau_la_OBJECTS = \ ++ xineplug_vo_out_vdpau_la-yuv2rgb.lo \ ++ xineplug_vo_out_vdpau_la-yuv2rgb_mmx.lo \ ++ xineplug_vo_out_vdpau_la-yuv2rgb_mlib.lo \ ++ xineplug_vo_out_vdpau_la-video_out_vdpau.lo ++xineplug_vo_out_vdpau_la_OBJECTS = \ ++ $(am_xineplug_vo_out_vdpau_la_OBJECTS) ++xineplug_vo_out_vdpau_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ ++ $(LIBTOOLFLAGS) --mode=link $(CCLD) \ ++ $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ ++ $(LDFLAGS) -o $@ ++@HAVE_VDPAU_TRUE@am_xineplug_vo_out_vdpau_la_rpath = -rpath \ ++@HAVE_VDPAU_TRUE@ $(xineplugdir) + xineplug_vo_out_vidix_la_DEPENDENCIES = $(XINE_LIB) \ + $(am__DEPENDENCIES_1) \ + $(top_builddir)/src/video_out/vidix/libvidix.la \ +@@ -435,6 +451,7 @@ SOURCES = $(libyuv2rgb_la_SOURCES) $(xin + $(xineplug_vo_out_sdl_la_SOURCES) \ + $(xineplug_vo_out_stk_la_SOURCES) \ + $(xineplug_vo_out_syncfb_la_SOURCES) \ ++ $(xineplug_vo_out_vdpau_la_SOURCES) \ + $(xineplug_vo_out_vidix_la_SOURCES) \ + $(xineplug_vo_out_xcbshm_la_SOURCES) \ + $(xineplug_vo_out_xcbxv_la_SOURCES) \ +@@ -458,6 +475,7 @@ DIST_SOURCES = $(libyuv2rgb_la_SOURCES) + $(xineplug_vo_out_sdl_la_SOURCES) \ + $(xineplug_vo_out_stk_la_SOURCES) \ + $(xineplug_vo_out_syncfb_la_SOURCES) \ ++ $(xineplug_vo_out_vdpau_la_SOURCES) \ + $(am__xineplug_vo_out_vidix_la_SOURCES_DIST) \ + $(am__xineplug_vo_out_xcbshm_la_SOURCES_DIST) \ + $(am__xineplug_vo_out_xcbxv_la_SOURCES_DIST) \ +@@ -845,6 +869,7 @@ VIDIX_CFLAGS = -I$(top_builddir)/src/vid + @HAVE_SYNCFB_TRUE@@HAVE_X11_TRUE@syncfb_module = xineplug_vo_out_syncfb.la + @HAVE_SUNDGA_TRUE@@HAVE_SUNFB_TRUE@@HAVE_X11_TRUE@pgx64_module = xineplug_vo_out_pgx64.la + @HAVE_SUNDGA_TRUE@@HAVE_SUNFB_TRUE@@HAVE_X11_TRUE@pgx32_module = xineplug_vo_out_pgx32.la ++@HAVE_VDPAU_TRUE@vdpau_module = xineplug_vo_out_vdpau.la + @HAVE_XCB_TRUE@XCBOSD = xcbosd.c + @HAVE_XCBSHM_TRUE@@HAVE_XCB_TRUE@xcbshm_module = xineplug_vo_out_xcbshm.la + @HAVE_XCBXV_TRUE@@HAVE_XCB_TRUE@xcbxv_module = xineplug_vo_out_xcbxv.la +@@ -879,9 +904,14 @@ xineplug_LTLIBRARIES = $(xshm_module) $( + $(xxmc_module) \ + $(xcbshm_module) \ + $(xcbxv_module) \ ++ $(vdpau_module) \ ++ $(rawvdpau_module) \ + xineplug_vo_out_raw.la \ + xineplug_vo_out_none.la + ++xineplug_vo_out_vdpau_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_vdpau.c ++xineplug_vo_out_vdpau_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) -lvdpau ++xineplug_vo_out_vdpau_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(X_CFLAGS) + xineplug_vo_out_xcbshm_la_SOURCES = video_out_xcbshm.c $(XCBOSD) + xineplug_vo_out_xcbshm_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL) + xineplug_vo_out_xcbshm_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS) +@@ -1070,6 +1100,8 @@ xineplug_vo_out_stk.la: $(xineplug_vo_ou + $(xineplug_vo_out_stk_la_LINK) $(am_xineplug_vo_out_stk_la_rpath) $(xineplug_vo_out_stk_la_OBJECTS) $(xineplug_vo_out_stk_la_LIBADD) $(LIBS) + xineplug_vo_out_syncfb.la: $(xineplug_vo_out_syncfb_la_OBJECTS) $(xineplug_vo_out_syncfb_la_DEPENDENCIES) + $(xineplug_vo_out_syncfb_la_LINK) $(am_xineplug_vo_out_syncfb_la_rpath) $(xineplug_vo_out_syncfb_la_OBJECTS) $(xineplug_vo_out_syncfb_la_LIBADD) $(LIBS) ++xineplug_vo_out_vdpau.la: $(xineplug_vo_out_vdpau_la_OBJECTS) $(xineplug_vo_out_vdpau_la_DEPENDENCIES) ++ $(xineplug_vo_out_vdpau_la_LINK) $(am_xineplug_vo_out_vdpau_la_rpath) $(xineplug_vo_out_vdpau_la_OBJECTS) $(xineplug_vo_out_vdpau_la_LIBADD) $(LIBS) + xineplug_vo_out_vidix.la: $(xineplug_vo_out_vidix_la_OBJECTS) $(xineplug_vo_out_vidix_la_DEPENDENCIES) + $(xineplug_vo_out_vidix_la_LINK) $(am_xineplug_vo_out_vidix_la_rpath) $(xineplug_vo_out_vidix_la_OBJECTS) $(xineplug_vo_out_vidix_la_LIBADD) $(LIBS) + xineplug_vo_out_xcbshm.la: $(xineplug_vo_out_xcbshm_la_OBJECTS) $(xineplug_vo_out_xcbshm_la_DEPENDENCIES) +@@ -1111,6 +1143,10 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_sdl_la-video_out_sdl.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_stk_la-video_out_stk.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_syncfb_la-video_out_syncfb.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_vdpau_la-video_out_vdpau.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mlib.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mmx.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_vidix_la-video_out_vidix.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_vidix_la-x11osd.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xineplug_vo_out_xcbshm_la-video_out_xcbshm.Plo@am__quote@ +@@ -1273,6 +1309,34 @@ xineplug_vo_out_syncfb_la-video_out_sync + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_syncfb_la_CFLAGS) $(CFLAGS) -c -o xineplug_vo_out_syncfb_la-video_out_syncfb.lo `test -f 'video_out_syncfb.c' || echo '$(srcdir)/'`video_out_syncfb.c + ++xineplug_vo_out_vdpau_la-yuv2rgb.lo: yuv2rgb.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -MT xineplug_vo_out_vdpau_la-yuv2rgb.lo -MD -MP -MF $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb.Tpo -c -o xineplug_vo_out_vdpau_la-yuv2rgb.lo `test -f 'yuv2rgb.c' || echo '$(srcdir)/'`yuv2rgb.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb.Tpo $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuv2rgb.c' object='xineplug_vo_out_vdpau_la-yuv2rgb.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -c -o xineplug_vo_out_vdpau_la-yuv2rgb.lo `test -f 'yuv2rgb.c' || echo '$(srcdir)/'`yuv2rgb.c ++ ++xineplug_vo_out_vdpau_la-yuv2rgb_mmx.lo: yuv2rgb_mmx.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -MT xineplug_vo_out_vdpau_la-yuv2rgb_mmx.lo -MD -MP -MF $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mmx.Tpo -c -o xineplug_vo_out_vdpau_la-yuv2rgb_mmx.lo `test -f 'yuv2rgb_mmx.c' || echo '$(srcdir)/'`yuv2rgb_mmx.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mmx.Tpo $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mmx.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuv2rgb_mmx.c' object='xineplug_vo_out_vdpau_la-yuv2rgb_mmx.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -c -o xineplug_vo_out_vdpau_la-yuv2rgb_mmx.lo `test -f 'yuv2rgb_mmx.c' || echo '$(srcdir)/'`yuv2rgb_mmx.c ++ ++xineplug_vo_out_vdpau_la-yuv2rgb_mlib.lo: yuv2rgb_mlib.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -MT xineplug_vo_out_vdpau_la-yuv2rgb_mlib.lo -MD -MP -MF $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mlib.Tpo -c -o xineplug_vo_out_vdpau_la-yuv2rgb_mlib.lo `test -f 'yuv2rgb_mlib.c' || echo '$(srcdir)/'`yuv2rgb_mlib.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mlib.Tpo $(DEPDIR)/xineplug_vo_out_vdpau_la-yuv2rgb_mlib.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='yuv2rgb_mlib.c' object='xineplug_vo_out_vdpau_la-yuv2rgb_mlib.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -c -o xineplug_vo_out_vdpau_la-yuv2rgb_mlib.lo `test -f 'yuv2rgb_mlib.c' || echo '$(srcdir)/'`yuv2rgb_mlib.c ++ ++xineplug_vo_out_vdpau_la-video_out_vdpau.lo: video_out_vdpau.c ++@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -MT xineplug_vo_out_vdpau_la-video_out_vdpau.lo -MD -MP -MF $(DEPDIR)/xineplug_vo_out_vdpau_la-video_out_vdpau.Tpo -c -o xineplug_vo_out_vdpau_la-video_out_vdpau.lo `test -f 'video_out_vdpau.c' || echo '$(srcdir)/'`video_out_vdpau.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_vo_out_vdpau_la-video_out_vdpau.Tpo $(DEPDIR)/xineplug_vo_out_vdpau_la-video_out_vdpau.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='video_out_vdpau.c' object='xineplug_vo_out_vdpau_la-video_out_vdpau.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vdpau_la_CFLAGS) $(CFLAGS) -c -o xineplug_vo_out_vdpau_la-video_out_vdpau.lo `test -f 'video_out_vdpau.c' || echo '$(srcdir)/'`video_out_vdpau.c ++ + xineplug_vo_out_vidix_la-video_out_vidix.lo: video_out_vidix.c + @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xineplug_vo_out_vidix_la_CFLAGS) $(CFLAGS) -MT xineplug_vo_out_vidix_la-video_out_vidix.lo -MD -MP -MF $(DEPDIR)/xineplug_vo_out_vidix_la-video_out_vidix.Tpo -c -o xineplug_vo_out_vidix_la-video_out_vidix.lo `test -f 'video_out_vidix.c' || echo '$(srcdir)/'`video_out_vidix.c + @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xineplug_vo_out_vidix_la-video_out_vidix.Tpo $(DEPDIR)/xineplug_vo_out_vidix_la-video_out_vidix.Plo +--- xine-lib-1.1.19.orig/src/libspudvb/xine_spudvb_decoder.c ++++ xine-lib-1.1.19/src/libspudvb/xine_spudvb_decoder.c +@@ -32,7 +32,11 @@ + #include "osd.h" + #define MAX_REGIONS 7 + +-/*#define LOG 1*/ ++#define SPU_MAX_WIDTH 720 ++#define SPU_MAX_HEIGHT 576 ++ ++/*#define LOG*/ ++#define LOG_MODULE "spudvb" + + typedef struct { + int x, y; +@@ -144,19 +148,15 @@ static void update_region (dvb_spu_decod + region_t *reg = &dvbsub->regions[region_id]; + + /* reject invalid sizes and set some limits ! */ +- if ( region_width<=0 || region_height<=0 || region_width>720 || region_height>576 ) { ++ if ( region_width<=0 || region_height<=0 || region_width>SPU_MAX_WIDTH || region_height>SPU_MAX_HEIGHT ) { + free( reg->img ); + reg->img = NULL; +-#ifdef LOG +- printf("SPUDVB: rejected region %d = %dx%d\n", region_id, region_width, region_height ); +-#endif ++ lprintf("rejected region %d = %dx%d\n", region_id, region_width, region_height ); + return; + } + + if ( (reg->width*reg->height) < (region_width*region_height) ) { +-#ifdef LOG +- printf("SPUDVB: update size of region %d = %dx%d\n", region_id, region_width, region_height); +-#endif ++ lprintf("update size of region %d = %dx%d\n", region_id, region_width, region_height); + free( reg->img ); + reg->img = NULL; + } +@@ -172,9 +172,7 @@ static void update_region (dvb_spu_decod + if ( fill ) { + memset( reg->img, fill_color, region_width*region_height ); + reg->empty = 1; +-#ifdef LOG +- printf("SPUDVB : FILL REGION %d\n", region_id); +-#endif ++ lprintf("FILL REGION %d\n", region_id); + } + reg->width = region_width; + reg->height = region_height; +@@ -243,58 +241,57 @@ static void decode_4bit_pixel_code_strin + const uint8_t switch_1 = (data & 0x08) >> 3; + bits++; + if (switch_1 == 0) { +- const uint8_t run_length = (data & 0x07); +- bits += 3; +- if (run_length != 0) { +- plot (this, r, run_length + 2, 0); +- } +- else { +- break; +- } ++ const uint8_t run_length = (data & 0x07); ++ bits += 3; ++ if (run_length != 0) { ++ plot (this, r, run_length + 2, 0); ++ } ++ else { ++ break; ++ } + } + else { +- const uint8_t switch_2 = (data & 0x04) >> 2; +- bits++; +- if (switch_2 == 0) { +- const uint8_t run_length = (data & 0x03); +- bits += 2; +- const uint8_t pixel_code = next_nibble (this); +- bits += 4; +- plot (this, r, run_length + 4, pixel_code); +- } +- else { +- const uint8_t switch_3 = (data & 0x03); +- bits += 2; +- switch (switch_3) { +- case 0: +- plot (this, r, 1, 0); +- break; +- case 1: +- plot (this, r, 2, 0); +- break; +- case 2: +- { +- const uint8_t run_length = next_nibble (this); +- bits += 4; +- const uint8_t pixel_code = next_nibble (this); +- bits += 4; +- plot (this, r, run_length + 9, pixel_code); +- } +- break; +- case 3: +- { +- uint8_t run_length = next_nibble (this); +- run_length = (run_length << 4) | next_nibble (this); +- bits += 8; +- const uint8_t pixel_code = next_nibble (this); +- bits += 4; +- plot (this, r, run_length + 25, pixel_code); +- } +- } +- } ++ const uint8_t switch_2 = (data & 0x04) >> 2; ++ bits++; ++ if (switch_2 == 0) { ++ const uint8_t run_length = (data & 0x03); ++ bits += 2; ++ const uint8_t pixel_code = next_nibble (this); ++ bits += 4; ++ plot (this, r, run_length + 4, pixel_code); ++ } ++ else { ++ const uint8_t switch_3 = (data & 0x03); ++ bits += 2; ++ switch (switch_3) { ++ case 0: ++ plot (this, r, 1, 0); ++ break; ++ case 1: ++ plot (this, r, 2, 0); ++ break; ++ case 2: ++ { ++ const uint8_t run_length = next_nibble (this); ++ bits += 4; ++ const uint8_t pixel_code = next_nibble (this); ++ bits += 4; ++ plot (this, r, run_length + 9, pixel_code); ++ } ++ break; ++ case 3: ++ { ++ uint8_t run_length = next_nibble (this); ++ run_length = (run_length << 4) | next_nibble (this); ++ bits += 8; ++ const uint8_t pixel_code = next_nibble (this); ++ bits += 4; ++ plot (this, r, run_length + 25, pixel_code); ++ } ++ } ++ } + } + } +- + } + if (dvbsub->nibble_flag == 1) { + dvbsub->i++; +@@ -614,13 +611,11 @@ static void* dvbsub_timer_func(void *thi + if(this && this->stream && this->stream->osd_renderer) { + int i; + for ( i=0; idvbsub->regions[i].osd ) +- continue; ++ if ( !this->dvbsub->regions[i].osd ) ++ continue; + +- this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 ); +-#ifdef LOG +- printf("SPUDVB: thread hiding = %d\n",i); +-#endif ++ this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 ); ++ lprintf("thread hiding = %d\n",i); + } + } + pthread_cond_wait(&this->dvbsub_restart_timeout, &this->dvbsub_osd_mutex); +@@ -647,7 +642,7 @@ static void draw_subtitles (dvb_spu_deco + int dest_width=0, dest_height; + this->stream->video_out->status(this->stream->video_out, NULL, &dest_width, &dest_height, &dum); + +- if ( !dest_width ) ++ if ( !dest_width || !dest_height ) + return; + + /* render all regions onto the page */ +@@ -657,8 +652,8 @@ static void draw_subtitles (dvb_spu_deco + int display = 0; + for ( r=0; rdvbsub->page.regions[r].is_visible ) { +- display = 1; +- break; ++ display = 1; ++ break; + } + } + if ( !display ) +@@ -670,58 +665,49 @@ static void draw_subtitles (dvb_spu_deco + if (this->dvbsub->regions[r].img) { + if (this->dvbsub->page.regions[r].is_visible && !this->dvbsub->regions[r].empty) { + update_osd( this, r ); +- if ( !this->dvbsub->regions[r].osd ) +- continue; ++ if ( !this->dvbsub->regions[r].osd ) ++ continue; + /* clear osd */ + this->stream->osd_renderer->clear( this->dvbsub->regions[r].osd ); + +- uint8_t *reg; +- int reg_width; +- uint8_t tmp[dest_width*576]; +- if (this->dvbsub->regions[r].width>dest_width) { +- downscale_region_image(&this->dvbsub->regions[r], tmp, dest_width); +- reg = tmp; +- reg_width = dest_width; +- } +- else { +- reg = this->dvbsub->regions[r].img; +- reg_width = this->dvbsub->regions[r].width; +- } +- this->stream->osd_renderer->set_palette( this->dvbsub->regions[r].osd, (uint32_t*)(&this->dvbsub->colours[this->dvbsub->regions[r].CLUT_id*256]), &this->dvbsub->trans[this->dvbsub->regions[r].CLUT_id*256]); +- this->stream->osd_renderer->draw_bitmap( this->dvbsub->regions[r].osd, reg, 0, 0, reg_width, this->dvbsub->regions[r].height, NULL ); ++ uint8_t *reg; ++ int reg_width; ++ uint8_t tmp[dest_width*576]; ++ if ( this->dvbsub->regions[r].width>dest_width && !(this->stream->video_driver->get_capabilities(this->stream->video_driver) & VO_CAP_CUSTOM_EXTENT_OVERLAY)) { ++ downscale_region_image(&this->dvbsub->regions[r], tmp, dest_width); ++ reg = tmp; ++ reg_width = dest_width; ++ } ++ else { ++ reg = this->dvbsub->regions[r].img; ++ reg_width = this->dvbsub->regions[r].width; ++ } ++ this->stream->osd_renderer->set_palette( this->dvbsub->regions[r].osd, (uint32_t*)(&this->dvbsub->colours[this->dvbsub->regions[r].CLUT_id*256]), &this->dvbsub->trans[this->dvbsub->regions[r].CLUT_id*256]); ++ this->stream->osd_renderer->draw_bitmap( this->dvbsub->regions[r].osd, reg, 0, 0, reg_width, this->dvbsub->regions[r].height, NULL ); + } + } + } + + pthread_mutex_lock(&this->dvbsub_osd_mutex); +-#ifdef LOG +- printf("SPUDVB: this->vpts=%llu\n",this->vpts); +-#endif ++ lprintf("this->vpts=%llu\n",this->vpts); + for ( r=0; rdvbsub->page.regions[r].is_visible, this->dvbsub->regions[r].osd?1:0, this->dvbsub->regions[r].empty ); +-#endif ++ lprintf("region=%d, visible=%d, osd=%d, empty=%d\n", r, this->dvbsub->page.regions[r].is_visible, this->dvbsub->regions[r].osd?1:0, this->dvbsub->regions[r].empty ); + if ( this->dvbsub->page.regions[r].is_visible && this->dvbsub->regions[r].osd && !this->dvbsub->regions[r].empty ) { ++ this->stream->osd_renderer->set_extent(this->dvbsub->regions[r].osd, SPU_MAX_WIDTH, SPU_MAX_HEIGHT); + this->stream->osd_renderer->set_position( this->dvbsub->regions[r].osd, this->dvbsub->page.regions[r].x, this->dvbsub->page.regions[r].y ); + this->stream->osd_renderer->show( this->dvbsub->regions[r].osd, this->vpts ); +-#ifdef LOG +- printf("SPUDVB: show region = %d\n",r); +-#endif ++ lprintf("show region = %d\n",r); + } + else { + if ( this->dvbsub->regions[r].osd ) { + this->stream->osd_renderer->hide( this->dvbsub->regions[r].osd, this->vpts ); +-#ifdef LOG +- printf("SPUDVB: hide region = %d\n",r); +-#endif ++ lprintf("hide region = %d\n",r); + } + } + } + this->dvbsub_hide_timeout.tv_nsec = 0; + this->dvbsub_hide_timeout.tv_sec = time(NULL) + this->dvbsub->page.page_time_out; +-#ifdef LOG +- printf("SPUDVB: page_time_out %d\n",this->dvbsub->page.page_time_out); +-#endif ++ lprintf("page_time_out %d\n",this->dvbsub->page.page_time_out); + pthread_cond_signal(&this->dvbsub_restart_timeout); + pthread_mutex_unlock(&this->dvbsub_osd_mutex); + } +@@ -747,7 +733,7 @@ static void spudec_decode_data (spu_deco + pthread_mutex_unlock(&this->dvbsub_osd_mutex); + } + else { +- xine_fast_memcpy (this->spu_descriptor, buf->decoder_info_ptr[2], buf->decoder_info[2]); ++ xine_fast_memcpy (this->spu_descriptor, buf->decoder_info_ptr[2], buf->decoder_info[2]); + } + } + return; +@@ -764,8 +750,8 @@ static void spudec_decode_data (spu_deco + } + else { + if (this->pes_pkt && (this->pes_pkt_wrptr != this->pes_pkt)) { +- xine_fast_memcpy (this->pes_pkt_wrptr, buf->content, buf->size); +- this->pes_pkt_wrptr += buf->size; ++ xine_fast_memcpy (this->pes_pkt_wrptr, buf->content, buf->size); ++ this->pes_pkt_wrptr += buf->size; + } + } + } +@@ -780,9 +766,7 @@ static void spudec_decode_data (spu_deco + metronom_clock_t *const clock = this->stream->xine->clock; + const int64_t curvpts = clock->get_current_time( clock ); + /* if buf->pts is unreliable, show page asap (better than nothing) */ +-#ifdef LOG +- printf("SPUDVB: spu_vpts=%lld - current_vpts=%lld\n", vpts, curvpts); +-#endif ++ lprintf("spu_vpts=%lld - current_vpts=%lld\n", vpts, curvpts); + if ( vpts<=curvpts || (vpts-curvpts)>(5*90000) ) + this->vpts = 0; + else +@@ -824,23 +808,23 @@ static void spudec_decode_data (spu_deco + /* SEGMENT_DATA_FIELD */ + switch (segment_type) { + case 0x10: +- process_page_composition_segment(this); +- break; ++ process_page_composition_segment(this); ++ break; + case 0x11: +- process_region_composition_segment(this); +- break; ++ process_region_composition_segment(this); ++ break; + case 0x12: +- process_CLUT_definition_segment(this); +- break; ++ process_CLUT_definition_segment(this); ++ break; + case 0x13: +- process_object_data_segment (this); +- break; ++ process_object_data_segment (this); ++ break; + case 0x80: +- draw_subtitles( this ); /* Page is now completely rendered */ +- break; ++ draw_subtitles( this ); /* Page is now completely rendered */ ++ break; + default: +- return; +- break; ++ return; ++ break; + } + } + this->dvbsub->i = new_i; +--- xine-lib-1.1.19.orig/src/demuxers/Makefile.am ++++ xine-lib-1.1.19/src/demuxers/Makefile.am +@@ -49,7 +49,8 @@ xineplug_LTLIBRARIES = $(ogg_module) $(a + xineplug_dmx_nsv.la \ + xineplug_dmx_matroska.la \ + xineplug_dmx_iff.la \ +- xineplug_dmx_flv.la ++ xineplug_dmx_flv.la \ ++ xineplug_dmx_vc1_es.la + + xineplug_dmx_ogg_la_SOURCES = demux_ogg.c + xineplug_dmx_ogg_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(OGG_LIBS) $(LTLIBINTL) +@@ -67,6 +68,9 @@ xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB + xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c + xineplug_dmx_mpeg_elem_la_LIBADD = $(XINE_LIB) + ++xineplug_dmx_vc1_es_la_SOURCES = demux_vc1es.c ++xineplug_dmx_vc1_es_la_LIBADD = $(XINE_LIB) ++ + xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c + xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) + +--- /dev/null ++++ xine-lib-1.1.19/src/demuxers/demux_vc1es.c +@@ -0,0 +1,453 @@ ++/* ++ * Copyright (C) 2008 the xine project ++ * Copyright (C) 2008 Christophe Thommeret ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ */ ++ ++/* ++ * demultiplexer for wmv9/vc1 elementary streams ++ * ++ * ++ * SMP (.rcv) format: ++ * ++ * ** header *** ++ * le24 number of frames ++ * C5 04 00 00 00 ++ * 4 bytes sequence header ++ * le32 height ++ * le32 width ++ * 0C 00 00 00 ++ * 8 bytes unknown ++ * le32 fps ++ * ************ ++ * le24 frame_size ++ * 80 ++ * le32 pts (ms) ++ * frame_size bytes of picture data ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* #define LOG */ ++#define LOG_MODULE "demux_vc1es" ++#define LOG_VERBOSE ++ ++#include "xine_internal.h" ++#include "xineutils.h" ++#include "compat.h" ++#include "bswap.h" ++#include "demux.h" ++ ++#define SCRATCH_SIZE 36 ++#define PRIVATE_SIZE 44 ++ ++#define MODE_SMP 1 ++#define MODE_AP 2 ++ ++ ++ ++typedef struct { ++ demux_plugin_t demux_plugin; ++ ++ xine_stream_t *stream; ++ fifo_buffer_t *video_fifo; ++ fifo_buffer_t *audio_fifo; ++ input_plugin_t *input; ++ int status; ++ int mode; ++ int first_chunk; ++ uint8_t private[PRIVATE_SIZE]; ++ uint32_t video_step; ++ ++ uint32_t blocksize; ++} demux_vc1_es_t ; ++ ++ ++ ++typedef struct { ++ demux_class_t demux_class; ++} demux_vc1_es_class_t; ++ ++ ++ ++static int demux_vc1_es_next_smp( demux_vc1_es_t *this ) ++{ ++ buf_element_t *buf; ++ uint32_t pts=0, frame_size=0; ++ off_t done; ++ uint8_t head[SCRATCH_SIZE]; ++ int start_flag = 1; ++ ++ if ( this->first_chunk ) { ++ this->input->read( this->input, head, SCRATCH_SIZE ); ++ this->first_chunk = 0; ++ } ++ ++ done = this->input->read( this->input, head, 8 ); ++ frame_size = _X_LE_24( head ); ++ pts = _X_LE_32( head+4 ); ++ ++ done = 0; ++ while ( frame_size>0 ) { ++ buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); ++ off_t read = (frame_size>buf->max_size) ? buf->max_size : frame_size; ++ done = this->input->read( this->input, buf->mem, read ); ++ if ( done<=0 ) { ++ buf->free_buffer( buf ); ++ this->status = DEMUX_FINISHED; ++ return 0; ++ } ++ buf->size = done; ++ buf->content = buf->mem; ++ buf->type = BUF_VIDEO_WMV9; ++ buf->pts = pts*90; ++ frame_size -= done; ++ if ( start_flag ) { ++ buf->decoder_flags = BUF_FLAG_FRAME_START; ++ start_flag = 0; ++ } ++ if ( !(frame_size>0) ) ++ buf->decoder_flags = BUF_FLAG_FRAME_END; ++ this->video_fifo->put(this->video_fifo, buf); ++ } ++ ++ return 1; ++} ++ ++ ++ ++static int demux_vc1_es_next_ap( demux_vc1_es_t *this ) ++{ ++ buf_element_t *buf; ++ uint32_t blocksize; ++ off_t done; ++ ++ buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); ++ blocksize = (this->blocksize ? this->blocksize : buf->max_size); ++ done = this->input->read(this->input, buf->mem, blocksize); ++ ++ if (done <= 0) { ++ buf->free_buffer (buf); ++ this->status = DEMUX_FINISHED; ++ return 0; ++ } ++ ++ buf->size = done; ++ buf->content = buf->mem; ++ buf->pts = 0; ++ buf->type = BUF_VIDEO_VC1; ++ ++ if( this->input->get_length (this->input) ) ++ buf->extra_info->input_normpos = (int)( (double)this->input->get_current_pos( this->input )*65535/this->input->get_length( this->input ) ); ++ ++ this->video_fifo->put(this->video_fifo, buf); ++ ++ return 1; ++} ++ ++ ++ ++static int demux_vc1_es_send_chunk( demux_plugin_t *this_gen ) ++{ ++ demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; ++ ++ if ( this->mode==MODE_SMP ) { ++ if (!demux_vc1_es_next_smp(this)) ++ this->status = DEMUX_FINISHED; ++ return this->status; ++ } ++ ++ if (!demux_vc1_es_next_ap(this)) ++ this->status = DEMUX_FINISHED; ++ return this->status; ++} ++ ++ ++ ++static int demux_vc1_es_get_status( demux_plugin_t *this_gen ) ++{ ++ demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; ++ ++ return this->status; ++} ++ ++ ++ ++static void demux_vc1_es_send_headers( demux_plugin_t *this_gen ) ++{ ++ demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; ++ ++ this->video_fifo = this->stream->video_fifo; ++ this->audio_fifo = this->stream->audio_fifo; ++ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); ++ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 0); ++ _x_demux_control_start(this->stream); ++ this->blocksize = this->input->get_blocksize(this->input); ++ this->status = DEMUX_OK; ++ ++ if ( this->mode==MODE_SMP ) { ++ buf_element_t *buf; ++ buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); ++ xine_fast_memcpy( buf->mem, this->private, PRIVATE_SIZE ); ++ buf->size = PRIVATE_SIZE; ++ buf->content = buf->mem; ++ buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; ++ if ( this->video_step ) { ++ buf->decoder_flags |= BUF_FLAG_FRAMERATE; ++ buf->decoder_info[0] = 90000/this->video_step; ++ } ++ buf->type = BUF_VIDEO_WMV9; ++ this->video_fifo->put(this->video_fifo, buf); ++ } ++} ++ ++ ++ ++static int demux_vc1_es_seek( demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing ) ++{ ++ demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; ++ ++ if ( this->mode==MODE_SMP ) { ++ this->status = DEMUX_OK; ++ return this->status; ++ } ++ ++ start_pos = (off_t) ( (double) start_pos / 65535 * ++ this->input->get_length (this->input) ); ++ ++ this->status = DEMUX_OK; ++ ++ if (playing) ++ _x_demux_flush_engine(this->stream); ++ ++ if (INPUT_IS_SEEKABLE(this->input)) { ++ ++ /* FIXME: implement time seek */ ++ ++ if (start_pos != this->input->seek (this->input, start_pos, SEEK_SET)) { ++ this->status = DEMUX_FINISHED; ++ return this->status; ++ } ++ lprintf ("seeking to %"PRId64"\n", start_pos); ++ } ++ ++ /* ++ * now start demuxing ++ */ ++ this->status = DEMUX_OK; ++ ++ return this->status; ++} ++ ++ ++ ++static void demux_vc1_es_dispose( demux_plugin_t *this ) ++{ ++ free (this); ++} ++ ++ ++ ++static int demux_vc1_es_get_stream_length( demux_plugin_t *this_gen ) ++{ ++ return 0 ; /*FIXME: implement */ ++} ++ ++ ++ ++static uint32_t demux_vc1_es_get_capabilities( demux_plugin_t *this_gen ) ++{ ++ return DEMUX_CAP_NOCAP; ++} ++ ++ ++ ++static int demux_vc1_es_get_optional_data( demux_plugin_t *this_gen, void *data, int data_type ) ++{ ++ return DEMUX_OPTIONAL_UNSUPPORTED; ++} ++ ++ ++ ++static demux_plugin_t *open_plugin( demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input ) ++{ ++ ++ demux_vc1_es_t *this; ++ uint8_t scratch[SCRATCH_SIZE]; ++ int i, read, found=0; ++ ++ switch (stream->content_detection_method) { ++ ++ case METHOD_BY_CONTENT: { ++ read = _x_demux_read_header(input, scratch, SCRATCH_SIZE); ++ if (!read) ++ return NULL; ++ lprintf("read size =%d\n",read); ++ ++ /* simple and main profiles */ ++ if ( read>=SCRATCH_SIZE ) { ++ lprintf("searching for rcv format..\n"); ++ if ( scratch[3]==0xc5 && scratch[4]==4 && scratch[5]==0 && scratch[6]==0 && scratch[7]==0 && scratch[20]==0x0c && scratch[21]==0 && scratch[22]==0 && scratch[23]==0 ) { ++ lprintf("rcv format found\n"); ++ found = MODE_SMP; ++ } ++ } ++ ++ if ( found==0 ) { ++ /* advanced profile */ ++ for (i = 0; i < read-4; i++) { ++ lprintf ("%02x %02x %02x %02x\n", scratch[i], scratch[i+1], scratch[i+2], scratch[i+3]); ++ if ((scratch[i] == 0x00) && (scratch[i+1] == 0x00) && (scratch[i+2] == 0x01)) { ++ if (scratch[i+3] == 0x0f) { ++ found = MODE_AP; ++ lprintf ("found header at offset 0x%x\n", i); ++ break; ++ } ++ } ++ } ++ } ++ ++ if (found == 0) ++ return NULL; ++ lprintf ("input accepted.\n"); ++ } ++ break; ++ ++ case METHOD_BY_EXTENSION: { ++ const char *extensions, *mrl; ++ ++ mrl = input->get_mrl (input); ++ extensions = class_gen->get_extensions (class_gen); ++ ++ if (!_x_demux_check_extension (mrl, extensions)) ++ return NULL; ++ } ++ break; ++ ++ case METHOD_EXPLICIT: ++ break; ++ ++ default: ++ return NULL; ++ } ++ ++ this = calloc(1, sizeof(demux_vc1_es_t)); ++ this->mode = found; ++ this->first_chunk = 1; ++ if ( found==MODE_SMP ) { ++ xine_fast_memcpy( this->private+8, scratch+12, 4 ); /* height */ ++ xine_fast_memcpy( this->private+4, scratch+16, 4 ); /* width */ ++ xine_fast_memcpy( this->private+40, scratch+8, 4 ); /* sequence header */ ++ this->video_step = _X_LE_32( scratch+32 ); ++ } ++ this->stream = stream; ++ this->input = input; ++ ++ this->demux_plugin.send_headers = demux_vc1_es_send_headers; ++ this->demux_plugin.send_chunk = demux_vc1_es_send_chunk; ++ this->demux_plugin.seek = demux_vc1_es_seek; ++ this->demux_plugin.dispose = demux_vc1_es_dispose; ++ this->demux_plugin.get_status = demux_vc1_es_get_status; ++ this->demux_plugin.get_stream_length = demux_vc1_es_get_stream_length; ++ this->demux_plugin.get_capabilities = demux_vc1_es_get_capabilities; ++ this->demux_plugin.get_optional_data = demux_vc1_es_get_optional_data; ++ this->demux_plugin.demux_class = class_gen; ++ ++ this->status = DEMUX_FINISHED; ++ ++ return &this->demux_plugin; ++} ++ ++ ++ ++static const char *get_description( demux_class_t *this_gen ) ++{ ++ return "VC1 elementary stream demux plugin"; ++} ++ ++ ++ ++static const char *get_identifier( demux_class_t *this_gen ) ++{ ++ return "VC1_ES"; ++} ++ ++ ++ ++static const char *get_extensions( demux_class_t *this_gen ) ++{ ++ return ""; ++} ++ ++ ++ ++static const char *get_mimetypes( demux_class_t *this_gen ) ++{ ++ return NULL; ++} ++ ++ ++ ++static void class_dispose( demux_class_t *this_gen ) ++{ ++ demux_vc1_es_class_t *this = (demux_vc1_es_class_t *) this_gen; ++ ++ free (this); ++} ++ ++ ++ ++static void *init_plugin( xine_t *xine, void *data ) ++{ ++ demux_vc1_es_class_t *this; ++ ++ this = calloc(1, sizeof(demux_vc1_es_class_t)); ++ ++ this->demux_class.open_plugin = open_plugin; ++ this->demux_class.get_description = get_description; ++ this->demux_class.get_identifier = get_identifier; ++ this->demux_class.get_mimetypes = get_mimetypes; ++ this->demux_class.get_extensions = get_extensions; ++ this->demux_class.dispose = class_dispose; ++ ++ return this; ++} ++ ++ ++/* ++ * exported plugin catalog entry ++ */ ++static const demuxer_info_t demux_info_vc1es = { ++ 0 /* priority */ ++}; ++ ++ ++ ++const plugin_info_t xine_plugin_info[] EXPORTED = { ++ /* type, API, "name", version, special_info, init_function */ ++ { PLUGIN_DEMUX, 26, "vc1es", XINE_VERSION_CODE, &demux_info_vc1es, init_plugin }, ++ { PLUGIN_NONE, 0, "", 0, NULL, NULL } ++}; +--- xine-lib-1.1.19.orig/src/demuxers/demux_mpeg.c ++++ xine-lib-1.1.19/src/demuxers/demux_mpeg.c +@@ -246,6 +246,8 @@ static void parse_mpeg2_packet (demux_mp + + len = read_bytes(this, 2); + ++ //printf( "parse_mpeg2_packet: stream_id=%X\n", stream_id); ++ + if (stream_id==0xbd) { + + int track; +@@ -483,7 +485,7 @@ static void parse_mpeg2_packet (demux_mp + + } + +- } else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) { ++ } else if ( ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) || stream_id==0xfd ) { + + w = read_bytes(this, 1); + flags = read_bytes(this, 1); +@@ -532,7 +534,7 @@ static void parse_mpeg2_packet (demux_mp + return; + } + +- buf->type = BUF_VIDEO_MPEG; ++ buf->type = (stream_id==0xfd) ? BUF_VIDEO_VC1 : BUF_VIDEO_MPEG; + buf->pts = pts; + buf->decoder_info[0] = pts - dts; + check_newpts( this, pts, PTS_VIDEO ); +--- xine-lib-1.1.19.orig/src/demuxers/Makefile.in ++++ xine-lib-1.1.19/src/demuxers/Makefile.in +@@ -227,6 +227,9 @@ xineplug_dmx_real_la_OBJECTS = $(am_xine + xineplug_dmx_slave_la_DEPENDENCIES = $(XINE_LIB) + am_xineplug_dmx_slave_la_OBJECTS = demux_slave.lo + xineplug_dmx_slave_la_OBJECTS = $(am_xineplug_dmx_slave_la_OBJECTS) ++xineplug_dmx_vc1_es_la_DEPENDENCIES = $(XINE_LIB) ++am_xineplug_dmx_vc1_es_la_OBJECTS = demux_vc1es.lo ++xineplug_dmx_vc1_es_la_OBJECTS = $(am_xineplug_dmx_vc1_es_la_OBJECTS) + xineplug_dmx_yuv4mpeg2_la_DEPENDENCIES = $(XINE_LIB) + am_xineplug_dmx_yuv4mpeg2_la_OBJECTS = demux_yuv4mpeg2.lo + xineplug_dmx_yuv4mpeg2_la_OBJECTS = \ +@@ -266,6 +269,7 @@ SOURCES = $(xineplug_dmx_asf_la_SOURCES) + $(xineplug_dmx_rawdv_la_SOURCES) \ + $(xineplug_dmx_real_la_SOURCES) \ + $(xineplug_dmx_slave_la_SOURCES) \ ++ $(xineplug_dmx_vc1_es_la_SOURCES) \ + $(xineplug_dmx_yuv4mpeg2_la_SOURCES) \ + $(xineplug_dmx_yuv_frames_la_SOURCES) + DIST_SOURCES = $(xineplug_dmx_asf_la_SOURCES) \ +@@ -286,6 +290,7 @@ DIST_SOURCES = $(xineplug_dmx_asf_la_SOU + $(xineplug_dmx_rawdv_la_SOURCES) \ + $(xineplug_dmx_real_la_SOURCES) \ + $(xineplug_dmx_slave_la_SOURCES) \ ++ $(xineplug_dmx_vc1_es_la_SOURCES) \ + $(xineplug_dmx_yuv4mpeg2_la_SOURCES) \ + $(xineplug_dmx_yuv_frames_la_SOURCES) + HEADERS = $(noinst_HEADERS) $(xineinclude_HEADERS) +@@ -644,7 +655,8 @@ xineplug_LTLIBRARIES = $(ogg_module) $(a + xineplug_dmx_nsv.la \ + xineplug_dmx_matroska.la \ + xineplug_dmx_iff.la \ +- xineplug_dmx_flv.la ++ xineplug_dmx_flv.la \ ++ xineplug_dmx_vc1_es.la + + xineplug_dmx_ogg_la_SOURCES = demux_ogg.c + xineplug_dmx_ogg_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(OGG_LIBS) $(LTLIBINTL) +@@ -657,6 +669,8 @@ xineplug_dmx_mpeg_la_SOURCES = demux_mpe + xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) + xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c + xineplug_dmx_mpeg_elem_la_LIBADD = $(XINE_LIB) ++xineplug_dmx_vc1_es_la_SOURCES = demux_vc1es.c ++xineplug_dmx_vc1_es_la_LIBADD = $(XINE_LIB) + xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c + xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) + xineplug_dmx_mpeg_ts_la_SOURCES = demux_ts.c +@@ -825,6 +839,8 @@ xineplug_dmx_real.la: $(xineplug_dmx_rea + $(LINK) -rpath $(xineplugdir) $(xineplug_dmx_real_la_OBJECTS) $(xineplug_dmx_real_la_LIBADD) $(LIBS) + xineplug_dmx_slave.la: $(xineplug_dmx_slave_la_OBJECTS) $(xineplug_dmx_slave_la_DEPENDENCIES) + $(LINK) -rpath $(xineplugdir) $(xineplug_dmx_slave_la_OBJECTS) $(xineplug_dmx_slave_la_LIBADD) $(LIBS) ++xineplug_dmx_vc1_es.la: $(xineplug_dmx_vc1_es_la_OBJECTS) $(xineplug_dmx_vc1_es_la_DEPENDENCIES) ++ $(LINK) -rpath $(xineplugdir) $(xineplug_dmx_vc1_es_la_OBJECTS) $(xineplug_dmx_vc1_es_la_LIBADD) $(LIBS) + xineplug_dmx_yuv4mpeg2.la: $(xineplug_dmx_yuv4mpeg2_la_OBJECTS) $(xineplug_dmx_yuv4mpeg2_la_DEPENDENCIES) + $(LINK) -rpath $(xineplugdir) $(xineplug_dmx_yuv4mpeg2_la_OBJECTS) $(xineplug_dmx_yuv4mpeg2_la_LIBADD) $(LIBS) + xineplug_dmx_yuv_frames.la: $(xineplug_dmx_yuv_frames_la_OBJECTS) $(xineplug_dmx_yuv_frames_la_DEPENDENCIES) +@@ -859,6 +875,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux_smjpeg.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux_str.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux_ts.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux_vc1es.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux_vmd.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux_vqa.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demux_wc3movie.Plo@am__quote@ +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/post_vdr_audio.c +@@ -0,0 +1,285 @@ ++/* ++ * Copyright (C) 2000-2004 the xine project ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ */ ++ ++/* ++ * select audio channel plugin for VDR ++ */ ++ ++#define LOG_MODULE "vdr_audio" ++#define LOG_VERBOSE ++/* ++#define LOG ++*/ ++ ++#include "xine_internal.h" ++#include "post.h" ++#include "combined_vdr.h" ++ ++ ++ ++typedef struct vdr_audio_post_plugin_s ++{ ++ post_plugin_t post_plugin; ++ ++ xine_event_queue_t *event_queue; ++ xine_stream_t *vdr_stream; ++ ++ uint8_t audio_channels; ++ int num_channels; ++ ++} ++vdr_audio_post_plugin_t; ++ ++ ++static void vdr_audio_select_audio(vdr_audio_post_plugin_t *this, uint8_t channels) ++{ ++ this->audio_channels = channels; ++} ++ ++ ++/* plugin class functions */ ++static post_plugin_t *vdr_audio_open_plugin(post_class_t *class_gen, int inputs, ++ xine_audio_port_t **audio_target, ++ xine_video_port_t **video_target); ++static char *vdr_audio_get_identifier(post_class_t *class_gen); ++static char *vdr_audio_get_description(post_class_t *class_gen); ++static void vdr_audio_class_dispose(post_class_t *class_gen); ++ ++/* plugin instance functions */ ++static void vdr_audio_dispose(post_plugin_t *this_gen); ++ ++/* replaced ao_port functions */ ++static int vdr_audio_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, ++ uint32_t bits, uint32_t rate, int mode); ++static void vdr_audio_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream); ++ ++ ++ ++void *vdr_audio_init_plugin(xine_t *xine, void *data) ++{ ++ post_class_t *class = (post_class_t *)xine_xmalloc(sizeof (post_class_t)); ++ ++ if (!class) ++ return NULL; ++ ++ class->open_plugin = vdr_audio_open_plugin; ++ class->get_identifier = vdr_audio_get_identifier; ++ class->get_description = vdr_audio_get_description; ++ class->dispose = vdr_audio_class_dispose; ++ ++ return class; ++} ++ ++static post_plugin_t *vdr_audio_open_plugin(post_class_t *class_gen, int inputs, ++ xine_audio_port_t **audio_target, ++ xine_video_port_t **video_target) ++{ ++ vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)xine_xmalloc(sizeof (vdr_audio_post_plugin_t)); ++ post_in_t *input; ++ post_out_t *output; ++ post_audio_port_t *port; ++/* ++fprintf(stderr, "~~~~~~~~~~ vdr open plugin\n"); ++*/ ++ if (!this || !audio_target || !audio_target[ 0 ]) ++ { ++ free(this); ++ return NULL; ++ } ++ ++ _x_post_init(&this->post_plugin, 1, 0); ++ this->post_plugin.dispose = vdr_audio_dispose; ++ ++ port = _x_post_intercept_audio_port(&this->post_plugin, audio_target[ 0 ], &input, &output); ++ port->new_port.open = vdr_audio_port_open; ++ port->new_port.put_buffer = vdr_audio_port_put_buffer; ++ ++ this->post_plugin.xine_post.audio_input[ 0 ] = &port->new_port; ++ ++ ++ ++ this->audio_channels = 0; ++ ++ return &this->post_plugin; ++} ++ ++static char *vdr_audio_get_identifier(post_class_t *class_gen) ++{ ++ return "vdr_audio"; ++} ++ ++static char *vdr_audio_get_description(post_class_t *class_gen) ++{ ++ return "modifies every audio frame as requested by VDR"; ++} ++ ++static void vdr_audio_class_dispose(post_class_t *class_gen) ++{ ++ free(class_gen); ++} ++ ++ ++static void vdr_audio_dispose(post_plugin_t *this_gen) ++{ ++/* ++fprintf(stderr, "~~~~~~~~~~ vdr dispose\n"); ++*/ ++ if (_x_post_dispose(this_gen)) ++ { ++ vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)this_gen; ++ ++ if (this->vdr_stream) ++ xine_event_dispose_queue(this->event_queue); ++ ++ free(this_gen); ++ } ++} ++ ++static int vdr_audio_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, ++ uint32_t bits, uint32_t rate, int mode) { ++ ++ post_audio_port_t *port = (post_audio_port_t *)port_gen; ++ vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)port->post; ++ ++ _x_post_rewire(&this->post_plugin); ++ _x_post_inc_usage(port); ++/* ++fprintf(stderr, "~~~~~~~~~~ vdr port open\n"); ++*/ ++ port->stream = stream; ++ port->bits = bits; ++ port->rate = rate; ++ port->mode = mode; ++ ++ this->num_channels = _x_ao_mode2channels(mode); ++ ++ return (port->original_port->open) (port->original_port, stream, bits, rate, mode ); ++} ++ ++ ++static void vdr_audio_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) ++{ ++ post_audio_port_t *port = (post_audio_port_t *)port_gen; ++ vdr_audio_post_plugin_t *this = (vdr_audio_post_plugin_t *)port->post; ++ xine_event_t *event; ++/* ++fprintf(stderr, "~~~~~~ vdr_audio\n"); ++*/ ++ if (this->vdr_stream ++ && !_x_continue_stream_processing(this->vdr_stream)) ++ { ++ this->vdr_stream = 0; ++ ++ xine_event_dispose_queue(this->event_queue); ++ this->event_queue = 0; ++ ++ this->audio_channels = 0; ++ } ++ ++ if (!this->vdr_stream ++ && vdr_is_vdr_stream(stream)) ++ { ++ this->event_queue = xine_event_new_queue(stream); ++ if (this->event_queue) ++ { ++ this->vdr_stream = stream; ++ ++ { ++ xine_event_t event; ++ ++ event.type = XINE_EVENT_VDR_PLUGINSTARTED; ++ event.data = 0; ++ event.data_length = 1; /* vdr_audio */ ++ ++ xine_event_send(this->vdr_stream, &event); ++ } ++ } ++ } ++ ++ if (this->event_queue) ++ { ++ while ((event = xine_event_get(this->event_queue))) ++ { ++ if (event->type == XINE_EVENT_VDR_SELECTAUDIO) ++ { ++ vdr_select_audio_data_t *data = (vdr_select_audio_data_t *)event->data; ++ ++ vdr_audio_select_audio(this, data->channels); ++ } ++ ++ xine_event_free(event); ++ } ++ } ++ ++ if (this->num_channels == 2 ++ && this->audio_channels != 0 ++ && this->audio_channels != 3) ++ { ++ audio_buffer_t *vdr_buf = port->original_port->get_buffer(port->original_port); ++ vdr_buf->num_frames = buf->num_frames; ++ vdr_buf->vpts = buf->vpts; ++ vdr_buf->frame_header_count = buf->frame_header_count; ++ vdr_buf->first_access_unit = buf->first_access_unit; ++ /* FIXME: The audio buffer should contain this info. ++ * We should not have to get it from the open call. ++ */ ++ vdr_buf->format.bits = buf->format.bits; ++ vdr_buf->format.rate = buf->format.rate; ++ vdr_buf->format.mode = buf->format.mode; ++ _x_extra_info_merge(vdr_buf->extra_info, buf->extra_info); ++ ++ { ++ int step = buf->format.bits / 8; ++ uint8_t *src = (uint8_t *)buf->mem; ++ uint8_t *dst = (uint8_t *)vdr_buf->mem; ++ ++ if (this->audio_channels == 2) ++ src += step; ++/* ++ fprintf(stderr, "~~~~~~~~~~ vdr port put buffer: channels: %d, %d\n" ++ , this->audio_channels ++ , buf->format.bits); ++*/ ++ int i, k; ++ for (i = 0; i < buf->num_frames; i++) ++ { ++ for (k = 0; k < step; k++) ++ *dst++ = *src++; ++ ++ src -= step; ++ ++ for (k = 0; k < step; k++) ++ *dst++ = *src++; ++ ++ src += step; ++ } ++ } ++ ++ /* pass data to original port */ ++ port->original_port->put_buffer(port->original_port, vdr_buf, stream); ++ ++ /* free data from origial buffer */ ++ buf->num_frames = 0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */ ++ } ++ ++ port->original_port->put_buffer(port->original_port, buf, stream); ++ ++ return; ++} +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/vdr.h +@@ -0,0 +1,665 @@ ++/* ++ * Copyright (C) 2000-2004 the xine project ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ */ ++ ++#ifndef __VDR_H ++#define __VDR_H ++ ++ ++#define XINE_VDR_VERSION 901 ++ ++ ++enum funcs ++{ ++ func_unknown = -1 ++ , func_nop ++ , func_osd_new ++ , func_osd_free ++ , func_osd_show ++ , func_osd_hide ++ , func_osd_set_position ++ , func_osd_draw_bitmap ++ , func_set_color ++ , func_clear ++ , func_mute ++ , func_set_volume ++ , func_set_speed ++ , func_set_prebuffer ++ , func_metronom ++ , func_start ++ , func_wait ++ , func_setup ++ , func_grab_image ++ , func_get_pts ++ , func_flush ++ , func_first_frame ++ , func_still_frame ++ , func_video_size ++ , func_set_video_window ++ , func_osd_flush ++ , func_play_external ++ , func_key ++ , func_frame_size ++ , func_reset_audio ++ , func_select_audio ++ , func_trick_speed_mode ++ , func_get_version ++ , func_discontinuity ++ , func_query_capabilities ++}; ++ ++enum keys ++{ ++ key_none, ++ key_up, ++ key_down, ++ key_menu, ++ key_ok, ++ key_back, ++ key_left, ++ key_right, ++ key_red, ++ key_green, ++ key_yellow, ++ key_blue, ++ key_0, ++ key_1, ++ key_2, ++ key_3, ++ key_4, ++ key_5, ++ key_6, ++ key_7, ++ key_8, ++ key_9, ++ key_play, ++ key_pause, ++ key_stop, ++ key_record, ++ key_fast_fwd, ++ key_fast_rew, ++ key_power, ++ key_channel_plus, ++ key_channel_minus, ++ key_volume_plus, ++ key_volume_minus, ++ key_mute, ++ key_schedule, ++ key_channels, ++ key_timers, ++ key_recordings, ++ key_setup, ++ key_commands, ++ key_user1, ++ key_user2, ++ key_user3, ++ key_user4, ++ key_user5, ++ key_user6, ++ key_user7, ++ key_user8, ++ key_user9, ++ key_audio, ++ key_info, ++ key_channel_previous, ++ key_next, ++ key_previous, ++ key_subtitles, ++}; ++ ++ ++ ++typedef struct __attribute__((packed)) data_header_s ++{ ++ uint32_t func:8; ++ uint32_t len:24; ++} ++data_header_t; ++ ++ ++ ++typedef data_header_t result_header_t; ++typedef data_header_t event_header_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_nop_s ++{ ++ data_header_t header; ++} ++data_nop_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_osd_new_s ++{ ++ data_header_t header; ++ ++ uint8_t window; ++ int16_t x; ++ int16_t y; ++ uint16_t width; ++ uint16_t height; ++ uint16_t w_ref; ++ uint16_t h_ref; ++} ++data_osd_new_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_osd_free_s ++{ ++ data_header_t header; ++ ++ uint8_t window; ++} ++data_osd_free_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_osd_show_s ++{ ++ data_header_t header; ++ ++ uint8_t window; ++} ++data_osd_show_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_osd_hide_s ++{ ++ data_header_t header; ++ ++ uint8_t window; ++} ++data_osd_hide_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_osd_flush_s ++{ ++ data_header_t header; ++} ++data_osd_flush_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_play_external_s ++{ ++ data_header_t header; ++} ++data_play_external_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_osd_set_position_s ++{ ++ data_header_t header; ++ ++ uint8_t window; ++ int16_t x; ++ int16_t y; ++} ++data_osd_set_position_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_osd_draw_bitmap_s ++{ ++ data_header_t header; ++ ++ uint8_t window; ++ int16_t x; ++ int16_t y; ++ uint16_t width; ++ uint16_t height; ++ uint8_t argb; ++} ++data_osd_draw_bitmap_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_set_color_s ++{ ++ data_header_t header; ++ ++ uint8_t window; ++ uint8_t index; ++ uint8_t num; ++} ++data_set_color_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_flush_s ++{ ++ data_header_t header; ++ ++ int32_t ms_timeout; ++ uint8_t just_wait; ++} ++data_flush_t; ++ ++ ++ ++typedef struct __attribute__((packed)) result_flush_s ++{ ++ result_header_t header; ++ ++ uint8_t timed_out; ++} ++result_flush_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_clear_s ++{ ++ data_header_t header; ++ ++ int32_t n; ++ int8_t s; ++ uint8_t i; ++} ++data_clear_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_mute_s ++{ ++ data_header_t header; ++ ++ uint8_t mute; ++} ++data_mute_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_set_volume_s ++{ ++ data_header_t header; ++ ++ uint8_t volume; ++} ++data_set_volume_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_set_speed_s ++{ ++ data_header_t header; ++ ++ int32_t speed; ++} ++data_set_speed_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_set_prebuffer_s ++{ ++ data_header_t header; ++ ++ uint32_t prebuffer; ++} ++data_set_prebuffer_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_metronom_s ++{ ++ data_header_t header; ++ ++ int64_t pts; ++ uint32_t flags; ++} ++data_metronom_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_start_s ++{ ++ data_header_t header; ++} ++data_start_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_wait_s ++{ ++ data_header_t header; ++ uint8_t id; ++} ++data_wait_t; ++ ++ ++ ++typedef struct __attribute__((packed)) result_wait_s ++{ ++ result_header_t header; ++} ++result_wait_t; ++ ++ ++ ++#define XINE_VDR_VOLUME_IGNORE 0 ++#define XINE_VDR_VOLUME_CHANGE_HW 1 ++#define XINE_VDR_VOLUME_CHANGE_SW 2 ++ ++#define XINE_VDR_MUTE_IGNORE 0 ++#define XINE_VDR_MUTE_EXECUTE 1 ++#define XINE_VDR_MUTE_SIMULATE 2 ++ ++typedef struct __attribute__((packed)) data_setup_s ++{ ++ data_header_t header; ++ ++ uint8_t osd_unscaled_blending; ++ uint8_t volume_mode; ++ uint8_t mute_mode; ++ uint16_t image4_3_zoom_x; ++ uint16_t image4_3_zoom_y; ++ uint16_t image16_9_zoom_x; ++ uint16_t image16_9_zoom_y; ++} ++data_setup_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_first_frame_s ++{ ++ data_header_t header; ++} ++data_first_frame_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_still_frame_s ++{ ++ data_header_t header; ++} ++data_still_frame_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_set_video_window_s ++{ ++ data_header_t header; ++ ++ uint32_t x; ++ uint32_t y; ++ uint32_t w; ++ uint32_t h; ++ uint32_t w_ref; ++ uint32_t h_ref; ++} ++data_set_video_window_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_grab_image_s ++{ ++ data_header_t header; ++} ++data_grab_image_t; ++ ++ ++ ++typedef struct __attribute__((packed)) result_grab_image_s ++{ ++ result_header_t header; ++ ++ int32_t width; ++ int32_t height; ++ int32_t ratio; ++ int32_t format; ++ int32_t interlaced; ++ int32_t crop_left; ++ int32_t crop_right; ++ int32_t crop_top; ++ int32_t crop_bottom; ++} ++result_grab_image_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_get_pts_s ++{ ++ data_header_t header; ++ int32_t ms_timeout; ++} ++data_get_pts_t; ++ ++ ++ ++typedef struct __attribute__((packed)) result_get_pts_s ++{ ++ result_header_t header; ++ ++ int64_t pts; ++ int8_t queued; ++} ++result_get_pts_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_get_version_s ++{ ++ data_header_t header; ++} ++data_get_version_t; ++ ++ ++ ++typedef struct __attribute__((packed)) result_get_version_s ++{ ++ result_header_t header; ++ ++ int32_t version; ++} ++result_get_version_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_video_size_s ++{ ++ data_header_t header; ++} ++data_video_size_t; ++ ++ ++ ++typedef struct __attribute__((packed)) result_video_size_s ++{ ++ result_header_t header; ++ ++ int32_t left; ++ int32_t top; ++ int32_t width; ++ int32_t height; ++ int32_t ratio; ++ int32_t zoom_x; ++ int32_t zoom_y; ++} ++result_video_size_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_reset_audio_s ++{ ++ data_header_t header; ++} ++data_reset_audio_t; ++ ++ ++ ++typedef struct __attribute__((packed)) event_key_s ++{ ++ event_header_t header; ++ ++ uint32_t key; ++} ++event_key_t; ++ ++ ++ ++typedef struct __attribute__((packed)) event_frame_size_s ++{ ++ event_header_t header; ++ ++ int32_t left; ++ int32_t top; ++ int32_t width; ++ int32_t height; ++ int32_t zoom_x; ++ int32_t zoom_y; ++} ++event_frame_size_t; ++ ++ ++ ++typedef struct __attribute__((packed)) event_play_external_s ++{ ++ event_header_t header; ++ ++ uint32_t key; ++} ++event_play_external_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_select_audio_s ++{ ++ data_header_t header; ++ ++ uint8_t channels; ++} ++data_select_audio_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_trick_speed_mode_s ++{ ++ data_header_t header; ++ ++ uint8_t on; ++} ++data_trick_speed_mode_t; ++ ++ ++ ++typedef struct __attribute__((packed)) event_discontinuity_s ++{ ++ event_header_t header; ++ ++ int32_t type; ++} ++event_discontinuity_t; ++ ++ ++ ++typedef struct __attribute__((packed)) data_query_capabilities_s ++{ ++ data_header_t header; ++} ++data_query_capabilities_t; ++ ++ ++ ++typedef struct __attribute__((packed)) result_query_capabilities_s ++{ ++ result_header_t header; ++ ++ uint8_t osd_max_num_windows; ++ uint8_t osd_palette_max_depth; ++ uint8_t osd_palette_is_shared; ++ uint8_t osd_supports_argb_layer; ++ uint8_t osd_supports_custom_extent; ++} ++result_query_capabilities_t; ++ ++ ++ ++typedef union __attribute__((packed)) data_union_u ++{ ++ data_header_t header; ++ data_nop_t nop; ++ data_osd_new_t osd_new; ++ data_osd_free_t osd_free; ++ data_osd_show_t osd_show; ++ data_osd_hide_t osd_hide; ++ data_osd_set_position_t osd_set_position; ++ data_osd_draw_bitmap_t osd_draw_bitmap; ++ data_set_color_t set_color; ++ data_flush_t flush; ++ data_clear_t clear; ++ data_mute_t mute; ++ data_set_volume_t set_volume; ++ data_set_speed_t set_speed; ++ data_set_prebuffer_t set_prebuffer; ++ data_metronom_t metronom; ++ data_start_t start; ++ data_wait_t wait; ++ data_setup_t setup; ++ data_grab_image_t grab_image; ++ data_get_pts_t get_pts; ++ data_first_frame_t first_frame; ++ data_still_frame_t still_frame; ++ data_video_size_t video_size; ++ data_set_video_window_t set_video_window; ++ data_osd_flush_t osd_flush; ++ data_play_external_t play_external; ++ data_reset_audio_t reset_audio; ++ data_select_audio_t select_audio; ++ data_trick_speed_mode_t trick_speed_mode; ++ data_get_version_t get_version; ++ data_query_capabilities_t query_capabilities; ++} ++data_union_t; ++ ++ ++ ++typedef union __attribute__((packed)) result_union_u ++{ ++ result_header_t header; ++ result_grab_image_t grab_image; ++ result_get_pts_t get_pts; ++ result_flush_t flush; ++ result_video_size_t video_size; ++ result_get_version_t get_version; ++ result_wait_t wait; ++ result_query_capabilities_t query_capabilities; ++} ++result_union_t; ++ ++ ++ ++typedef union __attribute__((packed)) event_union_u ++{ ++ event_header_t header; ++ event_key_t key; ++ event_frame_size_t frame_size; ++ event_play_external_t play_external; ++ event_discontinuity_t discontinuity; ++} ++event_union_t; ++ ++ ++ ++#endif /* __VDR_H */ ++ +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/input_vdr.c +@@ -0,0 +1,2665 @@ ++/* ++ * Copyright (C) 2003-2004 the xine project ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define LOG_MODULE "input_vdr" ++#define LOG_VERBOSE ++/* ++#define LOG ++*/ ++#include "xine_internal.h" ++#include "xineutils.h" ++#include "input_plugin.h" ++ ++#include "vdr.h" ++#include "combined_vdr.h" ++ ++ ++ ++#define VDR_MAX_NUM_WINDOWS 16 ++#define VDR_ABS_FIFO_DIR "/tmp/vdr-xine" ++ ++#define BUF_SIZE 1024 ++ ++#define LOG_OSD(x) ++/* ++#define LOG_OSD(x) x ++*/ ++ ++ ++typedef struct vdr_input_plugin_s vdr_input_plugin_t; ++ ++typedef struct ++{ ++ metronom_t metronom; ++ metronom_t *stream_metronom; ++ vdr_input_plugin_t *input; ++} ++vdr_metronom_t; ++ ++ ++typedef struct vdr_osd_s ++{ ++ xine_osd_t *window; ++ uint8_t *argb_buffer; ++ int width; ++ int height; ++} ++vdr_osd_t; ++ ++ ++typedef struct vdr_vpts_offset_s vdr_vpts_offset_t; ++ ++struct vdr_vpts_offset_s ++{ ++ vdr_vpts_offset_t *next; ++ int64_t vpts; ++ int64_t offset; ++}; ++ ++ ++struct vdr_input_plugin_s ++{ ++ input_plugin_t input_plugin; ++ ++ xine_stream_t *stream; ++ xine_stream_t *stream_external; ++ ++ int fh; ++ int fh_control; ++ int fh_result; ++ int fh_event; ++ ++ char *mrl; ++ ++ off_t curpos; ++ char seek_buf[ BUF_SIZE ]; ++ ++ char *preview; ++ off_t preview_size; ++ ++ enum funcs cur_func; ++ off_t cur_size; ++ off_t cur_done; ++ ++ vdr_osd_t osd[ VDR_MAX_NUM_WINDOWS ]; ++ uint8_t *osd_buffer; ++ uint32_t osd_buffer_size; ++ uint8_t osd_unscaled_blending; ++ uint8_t osd_supports_custom_extent; ++ uint8_t osd_supports_argb_layer; ++ ++ uint8_t audio_channels; ++ uint8_t trick_speed_mode; ++ uint8_t mute_mode; ++ uint8_t volume_mode; ++ int last_volume; ++ vdr_frame_size_changed_data_t frame_size; ++ ++ pthread_t rpc_thread; ++ int rpc_thread_shutdown; ++ pthread_mutex_t rpc_thread_shutdown_lock; ++ pthread_cond_t rpc_thread_shutdown_cond; ++ int startup_phase; ++ ++ pthread_t metronom_thread; ++ pthread_mutex_t metronom_thread_lock; ++ int64_t metronom_thread_request; ++ int metronom_thread_reply; ++ pthread_cond_t metronom_thread_request_cond; ++ pthread_cond_t metronom_thread_reply_cond; ++ pthread_mutex_t metronom_thread_call_lock; ++ ++ xine_event_queue_t *event_queue; ++ xine_event_queue_t *event_queue_external; ++ ++ pthread_mutex_t adjust_zoom_lock; ++ uint16_t image4_3_zoom_x; ++ uint16_t image4_3_zoom_y; ++ uint16_t image16_9_zoom_x; ++ uint16_t image16_9_zoom_y; ++ ++ uint8_t find_sync_point; ++ pthread_mutex_t find_sync_point_lock; ++ ++ vdr_metronom_t metronom; ++ int last_disc_type; ++ ++ vdr_vpts_offset_t *vpts_offset_queue; ++ vdr_vpts_offset_t *vpts_offset_queue_tail; ++ pthread_mutex_t vpts_offset_queue_lock; ++ pthread_cond_t vpts_offset_queue_changed_cond; ++ int vpts_offset_queue_changes; ++ ++ int video_window_active; ++ vdr_set_video_window_data_t video_window_event_data; ++}; ++ ++ ++typedef struct ++{ ++ input_class_t input_class; ++ xine_t *xine; ++ const char *mrls[ 2 ]; ++} ++vdr_input_class_t; ++ ++ ++ ++static int vdr_write(int f, void *b, int n) ++{ ++ int t = 0, r; ++ ++ while (t < n) ++ { ++ /* ++ * System calls are not a thread cancellation point in Linux ++ * pthreads. However, the RT signal sent to cancel the thread ++ * will cause recv() to return with EINTR, and we can manually ++ * check cancellation. ++ */ ++ pthread_testcancel(); ++ r = write(f, ((char *)b) + t, n - t); ++ pthread_testcancel(); ++ ++ if (r < 0 ++ && (errno == EINTR ++ || errno == EAGAIN)) ++ { ++ continue; ++ } ++ ++ if (r < 0) ++ return r; ++ ++ t += r; ++ } ++ ++ return t; ++} ++ ++ ++ ++static int internal_write_event_play_external(vdr_input_plugin_t *this, uint32_t key); ++ ++static void event_handler_external(void *user_data, const xine_event_t *event) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)user_data; ++ uint32_t key = key_none; ++/* ++ printf("event_handler_external(): event->type: %d\n", event->type); ++*/ ++ switch (event->type) ++ { ++ case XINE_EVENT_UI_PLAYBACK_FINISHED: ++ break; ++ ++ default: ++ return; ++ } ++ ++ if (0 != internal_write_event_play_external(this, key)) ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno)); ++} ++ ++static void external_stream_stop(vdr_input_plugin_t *this) ++{ ++ if (this->stream_external) ++ { ++ xine_stop(this->stream_external); ++ xine_close(this->stream_external); ++ ++ if (this->event_queue_external) ++ { ++ xine_event_dispose_queue(this->event_queue_external); ++ this->event_queue_external = 0; ++ } ++ ++ _x_demux_flush_engine(this->stream_external); ++ ++ xine_dispose(this->stream_external); ++ this->stream_external = 0; ++ } ++} ++ ++static void external_stream_play(vdr_input_plugin_t *this, char *file_name) ++{ ++ external_stream_stop(this); ++ ++ this->stream_external = xine_stream_new(this->stream->xine, this->stream->audio_out, this->stream->video_out); ++ ++ this->event_queue_external = xine_event_new_queue(this->stream_external); ++ ++ xine_event_create_listener_thread(this->event_queue_external, event_handler_external, this); ++ ++ if (!xine_open(this->stream_external, file_name) ++ || !xine_play(this->stream_external, 0, 0)) ++ { ++ uint32_t key = key_none; ++ ++ if ( 0 != internal_write_event_play_external(this, key)) ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno)); ++ } ++} ++ ++static off_t vdr_read_abort(xine_stream_t *stream, int fd, char *buf, off_t todo) ++{ ++ off_t ret; ++ ++ while (1) ++ { ++ /* ++ * System calls are not a thread cancellation point in Linux ++ * pthreads. However, the RT signal sent to cancel the thread ++ * will cause recv() to return with EINTR, and we can manually ++ * check cancellation. ++ */ ++ pthread_testcancel(); ++ ret = _x_read_abort(stream, fd, buf, todo); ++ pthread_testcancel(); ++ ++ if (ret < 0 ++ && (errno == EINTR ++ || errno == EAGAIN)) ++ { ++ continue; ++ } ++ ++ break; ++ } ++ ++ return ret; ++} ++ ++#define READ_DATA_OR_FAIL(kind, log) \ ++ data_##kind##_t *data = &data_union.kind; \ ++ { \ ++ log; \ ++ n = vdr_read_abort(this->stream, this->fh_control, (char *)data + sizeof (data->header), sizeof (*data) - sizeof (data->header)); \ ++ if (n != sizeof (*data) - sizeof (data->header)) \ ++ return -1; \ ++ \ ++ this->cur_size -= n; \ ++ } ++ ++static double _now() ++{ ++ struct timeval tv; ++ ++ gettimeofday(&tv, 0); ++ ++ return (tv.tv_sec * 1000000.0 + tv.tv_usec) / 1000.0; ++} ++ ++static void adjust_zoom(vdr_input_plugin_t *this) ++{ ++ pthread_mutex_lock(&this->adjust_zoom_lock); ++ ++ if (this->image4_3_zoom_x && this->image4_3_zoom_y ++ && this->image16_9_zoom_x && this->image16_9_zoom_y) ++ { ++ int ratio = (int)(10000 * this->frame_size.r + 0.5); ++ /* fprintf(stderr, "ratio: %d\n", ratio); */ ++ if (13332 <= ratio && ratio <= 13334) ++ { ++ xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, this->image4_3_zoom_x); ++ xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_Y, this->image4_3_zoom_y); ++ } ++ else /* if (17777 <= ratio && ratio <= 17779) */ ++ { ++ xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, this->image16_9_zoom_x); ++ xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_Y, this->image16_9_zoom_y); ++ } ++ } ++ ++ pthread_mutex_unlock(&this->adjust_zoom_lock); ++} ++ ++ ++static void vdr_vpts_offset_queue_process(vdr_input_plugin_t *this, int64_t vpts) ++{ ++ while (this->vpts_offset_queue ++ && this->vpts_offset_queue->vpts <= vpts) ++ { ++ vdr_vpts_offset_t *curr = this->vpts_offset_queue; ++ this->vpts_offset_queue = curr->next; ++ ++ free(curr); ++ } ++ ++ if (!this->vpts_offset_queue) ++ this->vpts_offset_queue_tail = 0; ++} ++ ++ ++static void vdr_vpts_offset_queue_purge(vdr_input_plugin_t *this) ++{ ++ vdr_vpts_offset_queue_process(this, 1ll << 62); ++} ++ ++ ++static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) ++{ ++ data_union_t data_union; ++ off_t n; ++ ++ n = vdr_read_abort(this->stream, this->fh_control, (char *)&data_union, sizeof (data_union.header)); ++ if (n != sizeof (data_union.header)) ++ return -1; ++ ++ this->cur_func = data_union.header.func; ++ this->cur_size = data_union.header.len - sizeof (data_union.header); ++ this->cur_done = 0; ++ ++ switch (this->cur_func) ++ { ++ case func_nop: ++ { ++ READ_DATA_OR_FAIL(nop, lprintf("got NOP\n")); ++ } ++ break; ++ ++ case func_osd_new: ++ { ++ READ_DATA_OR_FAIL(osd_new, LOG_OSD(lprintf("got OSDNEW\n"))); ++/* ++ LOG_OSD(lprintf("... (%d,%d)-(%d,%d)@(%d,%d)\n", data->x, data->y, data->width, data->height, data->w_ref, data->h_ref)); ++ ++ fprintf(stderr, "vdr: osdnew %d\n", data->window); ++*/ ++ if (data->window >= VDR_MAX_NUM_WINDOWS) ++ return -1; ++ ++ if (0 != this->osd[ data->window ].window) ++ return -1; ++ ++ this->osd[ data->window ].window = xine_osd_new(this->stream ++ , data->x ++ , data->y ++ , data->width ++ , data->height); ++ ++ this->osd[ data->window ].width = data->width; ++ this->osd[ data->window ].height = data->height; ++ ++ if (0 == this->osd[ data->window ].window) ++ return -1; ++ ++#ifdef XINE_OSD_CAP_CUSTOM_EXTENT ++ if (this->osd_supports_custom_extent && data->w_ref > 0 && data->h_ref > 0) ++ xine_osd_set_extent(this->osd[ data->window ].window, data->w_ref, data->h_ref); ++#endif ++ } ++ break; ++ ++ case func_osd_free: ++ { ++ READ_DATA_OR_FAIL(osd_free, LOG_OSD(lprintf("got OSDFREE\n"))); ++/* ++ fprintf(stderr, "vdr: osdfree %d\n", data->window); ++*/ ++ if (data->window >= VDR_MAX_NUM_WINDOWS) ++ return -1; ++ ++ if (0 != this->osd[ data->window ].window) ++ xine_osd_free(this->osd[ data->window ].window); ++ ++ this->osd[ data->window ].window = 0; ++ ++ free(this->osd[ data->window ].argb_buffer); ++ this->osd[ data->window ].argb_buffer = 0; ++ } ++ break; ++ ++ case func_osd_show: ++ { ++ READ_DATA_OR_FAIL(osd_show, LOG_OSD(lprintf("got OSDSHOW\n"))); ++/* ++ fprintf(stderr, "vdr: osdshow %d\n", data->window); ++*/ ++ if (data->window >= VDR_MAX_NUM_WINDOWS) ++ return -1; ++ ++ if (0 != this->osd[ data->window ].window) ++ { ++#ifdef XINE_OSD_CAP_VIDEO_WINDOW ++ xine_osd_set_video_window(this->osd[ data->window ].window ++ , this->video_window_active ? this->video_window_event_data.x : 0 ++ , this->video_window_active ? this->video_window_event_data.y : 0 ++ , this->video_window_active ? this->video_window_event_data.w : 0 ++ , this->video_window_active ? this->video_window_event_data.h : 0); ++#endif ++ if (this->osd_unscaled_blending) ++ xine_osd_show_unscaled(this->osd[ data->window ].window, 0); ++ else ++ xine_osd_show(this->osd[ data->window ].window, 0); ++ } ++ } ++ break; ++ ++ case func_osd_hide: ++ { ++ READ_DATA_OR_FAIL(osd_hide, LOG_OSD(lprintf("got OSDHIDE\n"))); ++/* ++ fprintf(stderr, "vdr: osdhide %d\n", data->window); ++*/ ++ if (data->window >= VDR_MAX_NUM_WINDOWS) ++ return -1; ++ ++ if (0 != this->osd[ data->window ].window) ++ xine_osd_hide(this->osd[ data->window ].window, 0); ++ } ++ break; ++ ++ case func_osd_flush: ++ { ++ double _t1, _t2; ++ int _n = 0; ++ int _to = 0; ++ int r = 0; ++ ++ READ_DATA_OR_FAIL(osd_flush, LOG_OSD(lprintf("got OSDFLUSH\n"))); ++/* ++ fprintf(stderr, "vdr: osdflush +\n"); ++*/ ++ _t1 = _now(); ++ ++ while ((r = _x_query_unprocessed_osd_events(this->stream))) ++ { ++ if ((_now() - _t1) > 200) ++ { ++ _to = 1; ++ break; ++ } ++/* ++ fprintf(stderr, "redraw_needed: 1\n"); ++*/ ++/* sched_yield(); */ ++ xine_usec_sleep(5000); ++ _n++; ++ } ++ ++ _t2 = _now(); ++ fprintf(stderr, "vdr: osdflush: n: %d, %.1lf, timeout: %d, result: %d\n", _n, _t2 - _t1, _to, r); ++/* ++ fprintf(stderr, "redraw_needed: 0\n"); ++ ++ fprintf(stderr, "vdr: osdflush -\n"); ++*/ ++ } ++ break; ++ ++ case func_osd_set_position: ++ { ++ READ_DATA_OR_FAIL(osd_set_position, LOG_OSD(lprintf("got OSDSETPOSITION\n"))); ++/* ++ fprintf(stderr, "vdr: osdsetposition %d\n", data->window); ++*/ ++ if (data->window >= VDR_MAX_NUM_WINDOWS) ++ return -1; ++ ++ if (0 != this->osd[ data->window ].window) ++ xine_osd_set_position(this->osd[ data->window ].window, data->x, data->y); ++ } ++ break; ++ ++ case func_osd_draw_bitmap: ++ { ++ READ_DATA_OR_FAIL(osd_draw_bitmap, LOG_OSD(lprintf("got OSDDRAWBITMAP\n"))); ++/* ++ fprintf(stderr, "vdr: osddrawbitmap %d, %d, %d, %d, %d, %d\n", data->window, data->x, data->y, data->width, data->height, data->argb); ++*/ ++ if (this->osd_buffer_size < this->cur_size) ++ { ++ if (this->osd_buffer) ++ free(this->osd_buffer); ++ ++ this->osd_buffer_size = 0; ++ ++ this->osd_buffer = xine_xmalloc(this->cur_size); ++ if (!this->osd_buffer) ++ return -1; ++ ++ this->osd_buffer_size = this->cur_size; ++ } ++ ++ n = vdr_read_abort (this->stream, this->fh_control, (char *)this->osd_buffer, this->cur_size); ++ if (n != this->cur_size) ++ return -1; ++ ++ this->cur_size -= n; ++ ++ if (data->window >= VDR_MAX_NUM_WINDOWS) ++ return -1; ++ ++ if (0 != this->osd[ data->window ].window) ++ { ++ vdr_osd_t *osd = &this->osd[ data->window ]; ++ ++ if (data->argb) ++ { ++ if (!osd->argb_buffer) ++ osd->argb_buffer = calloc(4 * osd->width, osd->height); ++ ++ { ++ int src_stride = 4 * data->width; ++ int dst_stride = 4 * osd->width; ++ ++ uint8_t *src = this->osd_buffer; ++ uint8_t *dst = osd->argb_buffer + data->y * dst_stride + data->x * 4; ++ int y; ++ ++ if (src_stride == dst_stride) ++ xine_fast_memcpy(dst, src, src_stride * data->height); ++ else ++ { ++ for (y = 0; y < data->height; y++) ++ { ++ xine_fast_memcpy(dst, src, src_stride); ++ dst += dst_stride; ++ src += src_stride; ++ } ++ } ++ } ++ ++#ifdef XINE_OSD_CAP_ARGB_LAYER ++ xine_osd_set_argb_buffer(osd->window, (uint32_t *)osd->argb_buffer, data->x, data->y, data->width, data->height); ++#endif ++ } ++ else ++ xine_osd_draw_bitmap(osd->window, this->osd_buffer, data->x, data->y, data->width, data->height, 0); ++ } ++ } ++ break; ++ ++ case func_set_color: ++ { ++ uint32_t vdr_color[ 256 ]; ++ ++ READ_DATA_OR_FAIL(set_color, lprintf("got SETCOLOR\n")); ++ ++ if (((data->num + 1) * sizeof (uint32_t)) != this->cur_size) ++ return -1; ++ ++ n = vdr_read_abort (this->stream, this->fh_control, (char *)&vdr_color[ data->index ], this->cur_size); ++ if (n != this->cur_size) ++ return -1; ++ ++ this->cur_size -= n; ++ ++ if (data->window >= VDR_MAX_NUM_WINDOWS) ++ return -1; ++ ++ if (0 != this->osd[ data->window ].window) ++ { ++ uint32_t color[ 256 ]; ++ uint8_t trans[ 256 ]; ++ ++ xine_osd_get_palette(this->osd[ data->window ].window, color, trans); ++ ++ { ++ int i; ++ ++ for (i = data->index; i <= (data->index + data->num); i++) ++ { ++ int a = (vdr_color[ i ] & 0xff000000) >> 0x18; ++ int r = (vdr_color[ i ] & 0x00ff0000) >> 0x10; ++ int g = (vdr_color[ i ] & 0x0000ff00) >> 0x08; ++ int b = (vdr_color[ i ] & 0x000000ff) >> 0x00; ++ ++ int y = (( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16; ++ int cr = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128; ++ int cb = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; ++ ++ uint8_t *dst = (uint8_t *)&color[ i ]; ++ *dst++ = cb; ++ *dst++ = cr; ++ *dst++ = y; ++ *dst++ = 0; ++ ++ trans[ i ] = a >> 4; ++ } ++ } ++ ++ xine_osd_set_palette(this->osd[ data->window ].window, color, trans); ++ } ++ } ++ break; ++ ++ case func_play_external: ++ { ++ char file_name[ 1024 ]; ++ int file_name_len = 0; ++ ++ READ_DATA_OR_FAIL(play_external, lprintf("got PLAYEXTERNAL\n")); ++ ++ file_name_len = this->cur_size; ++ ++ if (0 != file_name_len) ++ { ++ if (file_name_len <= 1 ++ || file_name_len > sizeof (file_name)) ++ { ++ return -1; ++ } ++ ++ n = vdr_read_abort (this->stream, this->fh_control, file_name, file_name_len); ++ if (n != file_name_len) ++ return -1; ++ ++ if (file_name[ file_name_len - 1 ] != '\0') ++ return -1; ++ ++ this->cur_size -= n; ++ } ++ ++ lprintf((file_name_len > 0) ? "----------- play external: %s\n" : "---------- stop external\n", file_name); ++ ++ if (file_name_len > 0) ++ external_stream_play(this, file_name); ++ else ++ external_stream_stop(this); ++ } ++ break; ++ ++ case func_clear: ++ { ++ READ_DATA_OR_FAIL(clear, lprintf("got CLEAR\n")); ++ ++ { ++ int orig_speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED); ++ if (orig_speed <= 0) ++ xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL); ++/* fprintf(stderr, "+++ CLEAR(%d%c): sync point: %02x\n", data->n, data->s ? 'b' : 'a', data->i); */ ++ if (!data->s) ++ { ++ pthread_mutex_lock(&this->find_sync_point_lock); ++ this->find_sync_point = data->i; ++ pthread_mutex_unlock(&this->find_sync_point_lock); ++ } ++/* ++ if (!this->dont_change_xine_volume) ++ xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, 0); ++*/ ++ _x_demux_flush_engine(this->stream); ++/* fprintf(stderr, "=== CLEAR(%d.1)\n", data->n); */ ++ _x_demux_control_start(this->stream); ++/* fprintf(stderr, "=== CLEAR(%d.2)\n", data->n); */ ++ _x_demux_seek(this->stream, 0, 0, 0); ++/* fprintf(stderr, "=== CLEAR(%d.3)\n", data->n); */ ++ ++ _x_stream_info_reset(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE); ++/* fprintf(stderr, "=== CLEAR(%d.4)\n", data->n); */ ++ _x_meta_info_reset(this->stream, XINE_META_INFO_AUDIOCODEC); ++/* fprintf(stderr, "=== CLEAR(%d.5)\n", data->n); */ ++ ++ _x_trigger_relaxed_frame_drop_mode(this->stream); ++/* _x_reset_relaxed_frame_drop_mode(this->stream); */ ++/* ++ if (!this->dont_change_xine_volume) ++ xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, this->last_volume); ++*/ ++/* fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a'); */ ++ if (orig_speed <= 0) ++ xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, orig_speed); ++ } ++ } ++ break; ++ ++ case func_first_frame: ++ { ++ READ_DATA_OR_FAIL(first_frame, lprintf("got FIRST FRAME\n")); ++ ++ _x_trigger_relaxed_frame_drop_mode(this->stream); ++/* _x_reset_relaxed_frame_drop_mode(this->stream); */ ++ } ++ break; ++ ++ case func_still_frame: ++ { ++ READ_DATA_OR_FAIL(still_frame, lprintf("got STILL FRAME\n")); ++ ++ _x_reset_relaxed_frame_drop_mode(this->stream); ++ } ++ break; ++ ++ case func_set_video_window: ++ { ++ READ_DATA_OR_FAIL(set_video_window, lprintf("got SET VIDEO WINDOW\n")); ++/* ++ fprintf(stderr, "svw: (%d, %d)x(%d, %d), (%d, %d)\n", data->x, data->y, data->w, data->h, data->wRef, data->hRef); ++*/ ++ { ++ xine_event_t event; ++ ++ this->video_window_active = (data->x != 0 ++ || data->y != 0 ++ || data->w != data->w_ref ++ || data->h != data->h_ref); ++ ++ this->video_window_event_data.x = data->x; ++ this->video_window_event_data.y = data->y; ++ this->video_window_event_data.w = data->w; ++ this->video_window_event_data.h = data->h; ++ this->video_window_event_data.w_ref = data->w_ref; ++ this->video_window_event_data.h_ref = data->h_ref; ++ ++ event.type = XINE_EVENT_VDR_SETVIDEOWINDOW; ++ event.data = &this->video_window_event_data; ++ event.data_length = sizeof (this->video_window_event_data); ++ ++ xine_event_send(this->stream, &event); ++ } ++ } ++ break; ++ ++ case func_select_audio: ++ { ++ READ_DATA_OR_FAIL(select_audio, lprintf("got SELECT AUDIO\n")); ++ ++ this->audio_channels = data->channels; ++ ++ { ++ xine_event_t event; ++ vdr_select_audio_data_t event_data; ++ ++ event_data.channels = this->audio_channels; ++ ++ event.type = XINE_EVENT_VDR_SELECTAUDIO; ++ event.data = &event_data; ++ event.data_length = sizeof (event_data); ++ ++ xine_event_send(this->stream, &event); ++ } ++ } ++ break; ++ ++ case func_trick_speed_mode: ++ { ++ READ_DATA_OR_FAIL(trick_speed_mode, lprintf("got TRICK SPEED MODE\n")); ++ ++ if (this->trick_speed_mode != data->on) ++ { ++ this->trick_speed_mode = data->on; ++ ++ _x_demux_seek(this->stream, 0, 0, 0); ++ ++ { ++ xine_event_t event; ++ ++ event.type = XINE_EVENT_VDR_TRICKSPEEDMODE; ++ event.data = 0; ++ event.data_length = 0; /* this->trick_speed_mode; */ ++/* fprintf(stderr, "************************: %p, %d\n", event.data, event.data_length); */ ++ xine_event_send(this->stream, &event); ++ } ++ } ++ } ++ break; ++ ++ case func_flush: ++ { ++ READ_DATA_OR_FAIL(flush, lprintf("got FLUSH\n")); ++ ++ if (!data->just_wait) ++ { ++ if (this->stream->video_fifo) ++ { ++ buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); ++ if (!buf) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: buffer_pool_alloc() failed!\n"), LOG_MODULE); ++ return -1; ++ } ++ ++ buf->type = BUF_CONTROL_FLUSH_DECODER; ++ ++ this->stream->video_fifo->put(this->stream->video_fifo, buf); ++ } ++ } ++ ++ { ++ double _t1, _t2; ++ int _n = 0; ++ ++ int vb = -1, ab = -1, vf = -1, af = -1; ++ ++ uint8_t timed_out = 0; ++ ++ struct timeval now, then; ++ ++ if (data->ms_timeout >= 0) ++ { ++ gettimeofday(&now, 0); ++ ++ then = now; ++ then.tv_usec += (data->ms_timeout % 1000) * 1000; ++ then.tv_sec += (data->ms_timeout / 1000); ++ ++ if (then.tv_usec >= 1000000) ++ { ++ then.tv_usec -= 1000000; ++ then.tv_sec += 1; ++ } ++ } ++ else ++ { ++ then.tv_usec = 0; ++ then.tv_sec = 0; ++ } ++ ++ _t1 = _now(); ++ ++ while (1) ++ { ++ _x_query_buffer_usage(this->stream, &vb, &ab, &vf, &af); ++ ++ if (vb <= 0 && ab <= 0 && vf <= 0 && af <= 0) ++ break; ++ ++ if (data->ms_timeout >= 0 ++ && timercmp(&now, &then, >=)) ++ { ++ timed_out++; ++ break; ++ } ++ ++/* sched_yield(); */ ++ xine_usec_sleep(5000); ++ _n++; ++ ++ if (data->ms_timeout >= 0) ++ gettimeofday(&now, 0); ++ } ++ ++ _t2 = _now(); ++ /* fprintf(stderr, "vdr: flush: n: %d, %.1lf\n", _n, _t2 - _t1); */ ++ ++ xprintf(this->stream->xine ++ , XINE_VERBOSITY_LOG ++ , _("%s: flush buffers (vb: %d, ab: %d, vf: %d, af: %d) %s.\n") ++ , LOG_MODULE, vb, ab, vf, af ++ , (timed_out ? "timed out" : "done")); ++ ++ { ++ result_flush_t result_flush; ++ result_flush.header.func = data->header.func; ++ result_flush.header.len = sizeof (result_flush); ++ ++ result_flush.timed_out = timed_out; ++ ++ if (sizeof (result_flush) != vdr_write(this->fh_result, &result_flush, sizeof (result_flush))) ++ return -1; ++ } ++ } ++ } ++ break; ++ ++ case func_mute: ++ { ++ READ_DATA_OR_FAIL(mute, lprintf("got MUTE\n")); ++ ++ { ++ int param_mute = (this->volume_mode == XINE_VDR_VOLUME_CHANGE_SW) ? XINE_PARAM_AUDIO_AMP_MUTE : XINE_PARAM_AUDIO_MUTE; ++ xine_set_param(this->stream, param_mute, data->mute); ++ } ++ } ++ break; ++ ++ case func_set_volume: ++ { ++double t3, t2, t1, t0; ++ READ_DATA_OR_FAIL(set_volume, lprintf("got SETVOLUME\n")); ++t0 = _now(); ++ { ++ int change_volume = (this->volume_mode != XINE_VDR_VOLUME_IGNORE); ++ int do_mute = (this->last_volume != 0 && 0 == data->volume); ++ int do_unmute = (this->last_volume <= 0 && 0 != data->volume); ++ int report_change = 0; ++ ++ int param_mute = (this->volume_mode == XINE_VDR_VOLUME_CHANGE_SW) ? XINE_PARAM_AUDIO_AMP_MUTE : XINE_PARAM_AUDIO_MUTE; ++ int param_volume = (this->volume_mode == XINE_VDR_VOLUME_CHANGE_SW) ? XINE_PARAM_AUDIO_AMP_LEVEL : XINE_PARAM_AUDIO_VOLUME; ++ ++ this->last_volume = data->volume; ++ ++ if (do_mute || do_unmute) ++ { ++ switch (this->mute_mode) ++ { ++ case XINE_VDR_MUTE_EXECUTE: ++ report_change = 1; ++ xine_set_param(this->stream, param_mute, do_mute); ++ ++ case XINE_VDR_MUTE_IGNORE: ++ if (do_mute) ++ change_volume = 0; ++ break; ++ ++ case XINE_VDR_MUTE_SIMULATE: ++ change_volume = 1; ++ break; ++ ++ default: ++ return -1; ++ }; ++ } ++t1 = _now(); ++ ++ if (change_volume) ++ { ++ report_change = 1; ++ xine_set_param(this->stream, param_volume, this->last_volume); ++ } ++t2 = _now(); ++ ++ if (report_change && this->volume_mode != XINE_VDR_VOLUME_CHANGE_SW) ++ { ++ xine_event_t event; ++ xine_audio_level_data_t data; ++ ++ data.left ++ = data.right ++ = xine_get_param(this->stream, param_volume); ++ data.mute ++ = xine_get_param(this->stream, param_mute); ++t3 = _now(); ++ ++ event.type = XINE_EVENT_AUDIO_LEVEL; ++ event.data = &data; ++ event.data_length = sizeof (data); ++ ++ xine_event_send(this->stream, &event); ++ } ++ } ++/* fprintf(stderr, "volume: %6.3lf ms, %6.3lf ms, %6.3lf ms\n", t1 - t0, t2 - t1, t3 - t2); */ ++ } ++ break; ++ ++ case func_set_speed: ++ { ++ READ_DATA_OR_FAIL(set_speed, lprintf("got SETSPEED\n")); ++ ++ lprintf("... got SETSPEED %d\n", data->speed); ++ ++ if (data->speed != xine_get_param(this->stream, XINE_PARAM_FINE_SPEED)) ++ xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, data->speed); ++ } ++ break; ++ ++ case func_set_prebuffer: ++ { ++ READ_DATA_OR_FAIL(set_prebuffer, lprintf("got SETPREBUFFER\n")); ++ ++ xine_set_param(this->stream, XINE_PARAM_METRONOM_PREBUFFER, data->prebuffer); ++ } ++ break; ++ ++ case func_metronom: ++ { ++ READ_DATA_OR_FAIL(metronom, lprintf("got METRONOM\n")); ++ ++ _x_demux_control_newpts(this->stream, data->pts, data->flags); ++ } ++ break; ++ ++ case func_start: ++ { ++ READ_DATA_OR_FAIL(start, lprintf("got START\n")); ++ ++ _x_demux_control_start(this->stream); ++ _x_demux_seek(this->stream, 0, 0, 0); ++ } ++ break; ++ ++ case func_wait: ++ { ++ READ_DATA_OR_FAIL(wait, lprintf("got WAIT\n")); ++ ++ { ++ result_wait_t result_wait; ++ result_wait.header.func = data->header.func; ++ result_wait.header.len = sizeof (result_wait); ++ ++ if (sizeof (result_wait) != vdr_write(this->fh_result, &result_wait, sizeof (result_wait))) ++ return -1; ++ ++ if (data->id == 1) ++ this->startup_phase = 0; ++ } ++ } ++ break; ++ ++ case func_setup: ++ { ++ READ_DATA_OR_FAIL(setup, lprintf("got SETUP\n")); ++ ++ this->osd_unscaled_blending = data->osd_unscaled_blending; ++ this->volume_mode = data->volume_mode; ++ this->mute_mode = data->mute_mode; ++ this->image4_3_zoom_x = data->image4_3_zoom_x; ++ this->image4_3_zoom_y = data->image4_3_zoom_y; ++ this->image16_9_zoom_x = data->image16_9_zoom_x; ++ this->image16_9_zoom_y = data->image16_9_zoom_y; ++ ++ adjust_zoom(this); ++ } ++ break; ++ ++ case func_grab_image: ++ { ++ READ_DATA_OR_FAIL(grab_image, lprintf("got GRABIMAGE\n")); ++ ++ { ++ off_t ret_val = -1; ++ ++ xine_current_frame_data_t frame_data; ++ memset(&frame_data, 0, sizeof (frame_data)); ++ ++ if (xine_get_current_frame_data(this->stream, &frame_data, XINE_FRAME_DATA_ALLOCATE_IMG)) ++ { ++ if (frame_data.ratio_code == XINE_VO_ASPECT_SQUARE) ++ frame_data.ratio_code = 10000; ++ else if (frame_data.ratio_code == XINE_VO_ASPECT_4_3) ++ frame_data.ratio_code = 13333; ++ else if (frame_data.ratio_code == XINE_VO_ASPECT_ANAMORPHIC) ++ frame_data.ratio_code = 17778; ++ else if (frame_data.ratio_code == XINE_VO_ASPECT_DVB) ++ frame_data.ratio_code = 21100; ++ } ++ ++ if (!frame_data.img) ++ memset(&frame_data, 0, sizeof (frame_data)); ++ ++ { ++ result_grab_image_t result_grab_image; ++ result_grab_image.header.func = data->header.func; ++ result_grab_image.header.len = sizeof (result_grab_image) + frame_data.img_size; ++ ++ result_grab_image.width = frame_data.width; ++ result_grab_image.height = frame_data.height; ++ result_grab_image.ratio = frame_data.ratio_code; ++ result_grab_image.format = frame_data.format; ++ result_grab_image.interlaced = frame_data.interlaced; ++ result_grab_image.crop_left = frame_data.crop_left; ++ result_grab_image.crop_right = frame_data.crop_right; ++ result_grab_image.crop_top = frame_data.crop_top; ++ result_grab_image.crop_bottom = frame_data.crop_bottom; ++ ++ if (sizeof (result_grab_image) == vdr_write(this->fh_result, &result_grab_image, sizeof (result_grab_image))) ++ { ++ if (!frame_data.img_size || (frame_data.img_size == vdr_write(this->fh_result, frame_data.img, frame_data.img_size))) ++ ret_val = 0; ++ } ++ } ++ ++ free(frame_data.img); ++ ++ if (ret_val != 0) ++ return ret_val; ++ } ++ } ++ break; ++ ++ case func_get_pts: ++ { ++ READ_DATA_OR_FAIL(get_pts, lprintf("got GETPTS\n")); ++ ++ { ++ result_get_pts_t result_get_pts; ++ result_get_pts.header.func = data->header.func; ++ result_get_pts.header.len = sizeof (result_get_pts); ++ ++ pthread_mutex_lock(&this->vpts_offset_queue_lock); ++ ++ while (this->vpts_offset_queue_changes) ++ pthread_cond_wait(&this->vpts_offset_queue_changed_cond, &this->vpts_offset_queue_lock); ++ ++ if (this->last_disc_type == DISC_STREAMSTART ++ && data->ms_timeout > 0) ++ { ++ struct timespec abstime; ++ { ++ struct timeval now; ++ gettimeofday(&now, 0); ++ ++ abstime.tv_sec = now.tv_sec + data->ms_timeout / 1000; ++ abstime.tv_nsec = now.tv_usec * 1000 + (data->ms_timeout % 1000) * 1e6; ++ ++ if (abstime.tv_nsec > 1e9) ++ { ++ abstime.tv_nsec -= 1e9; ++ abstime.tv_sec++; ++ } ++ } ++ ++ while (this->last_disc_type == DISC_STREAMSTART ++ || this->vpts_offset_queue_changes) ++ { ++ if (0 != pthread_cond_timedwait(&this->vpts_offset_queue_changed_cond, &this->vpts_offset_queue_lock, &abstime)) ++ break; ++ } ++ } ++ ++ if (this->last_disc_type == DISC_STREAMSTART ++ || this->vpts_offset_queue_changes) ++ { ++ result_get_pts.pts = -1; ++ result_get_pts.queued = 0; ++ } ++ else ++ { ++ int64_t offset, vpts = xine_get_current_vpts(this->stream); ++ ++ vdr_vpts_offset_queue_process(this, vpts); ++ ++/* if(this->vpts_offset_queue) */ ++if(0) ++ { ++fprintf(stderr, "C ---------------------------------------------\n"); ++ vdr_vpts_offset_t *p = this->vpts_offset_queue; ++ while (p) ++ { ++ fprintf(stderr, "C now: %12"PRId64", vpts: %12"PRId64", offset: %12"PRId64"\n", xine_get_current_vpts(this->stream), p->vpts, p->offset); ++ p = p->next; ++ } ++fprintf(stderr, "C =============================================\n"); ++ } ++ ++ if (this->vpts_offset_queue) ++ offset = this->vpts_offset_queue->offset; ++ else ++ offset = this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET); ++ ++ result_get_pts.pts = (vpts - offset) & ((1ll << 33) - 1); ++ result_get_pts.queued = !!this->vpts_offset_queue; ++/* fprintf(stderr, "vpts: %12ld, stc: %12ld, offset: %12ld\n", vpts, result_get_pts.pts, offset); */ ++ } ++ ++ pthread_mutex_unlock(&this->vpts_offset_queue_lock); ++ ++ if (sizeof (result_get_pts) != vdr_write(this->fh_result, &result_get_pts, sizeof (result_get_pts))) ++ return -1; ++ } ++ } ++ break; ++ ++ case func_get_version: ++ { ++ READ_DATA_OR_FAIL(get_version, lprintf("got GETVERSION\n")); ++ ++ { ++ result_get_version_t result_get_version; ++ result_get_version.header.func = data->header.func; ++ result_get_version.header.len = sizeof (result_get_version); ++ ++ result_get_version.version = XINE_VDR_VERSION; ++ ++ if (sizeof (result_get_version) != vdr_write(this->fh_result, &result_get_version, sizeof (result_get_version))) ++ return -1; ++ } ++ } ++ break; ++ ++ case func_video_size: ++ { ++ READ_DATA_OR_FAIL(video_size, lprintf("got VIDEO SIZE\n")); ++ ++ { ++ int format; ++ ++ result_video_size_t result_video_size; ++ result_video_size.header.func = data->header.func; ++ result_video_size.header.len = sizeof (result_video_size); ++ ++ result_video_size.top = -1; ++ result_video_size.left = -1; ++ result_video_size.width = -1; ++ result_video_size.height = -1; ++ result_video_size.ratio = 0; ++ ++ xine_get_current_frame(this->stream, &result_video_size.width, &result_video_size.height, &result_video_size.ratio, &format, 0); ++ ++ if (result_video_size.ratio == XINE_VO_ASPECT_SQUARE) ++ result_video_size.ratio = 10000; ++ else if (result_video_size.ratio == XINE_VO_ASPECT_4_3) ++ result_video_size.ratio = 13333; ++ else if (result_video_size.ratio == XINE_VO_ASPECT_ANAMORPHIC) ++ result_video_size.ratio = 17778; ++ else if (result_video_size.ratio == XINE_VO_ASPECT_DVB) ++ result_video_size.ratio = 21100; ++ ++ if (0 != this->frame_size.x ++ || 0 != this->frame_size.y ++ || 0 != this->frame_size.w ++ || 0 != this->frame_size.h) ++ { ++ result_video_size.left = this->frame_size.x; ++ result_video_size.top = this->frame_size.y; ++ result_video_size.width = this->frame_size.w; ++ result_video_size.height = this->frame_size.h; ++ } ++/* fprintf(stderr, "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n"); */ ++ result_video_size.zoom_x = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_X); ++ result_video_size.zoom_y = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_Y); ++/* fprintf(stderr, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n"); */ ++ if (sizeof (result_video_size) != vdr_write(this->fh_result, &result_video_size, sizeof (result_video_size))) ++ return -1; ++/* fprintf(stderr, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n"); */ ++ } ++ } ++ break; ++ ++ case func_reset_audio: ++ { ++ double _t1, _t2; ++ int _n = 0; ++ ++ READ_DATA_OR_FAIL(reset_audio, lprintf("got RESET AUDIO\n")); ++ ++ if (this->stream->audio_fifo) ++ { ++ xine_set_param(this->stream, XINE_PARAM_IGNORE_AUDIO, 1); ++ xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -2); ++ ++ _t1 = _now(); ++ ++ while (1) ++ { ++ int n = xine_get_stream_info(this->stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL); ++ if (n <= 0) ++ break; ++ ++ /* keep the decoder running */ ++ if (this->stream->audio_fifo) ++ { ++ buf_element_t *buf = this->stream->audio_fifo->buffer_pool_alloc(this->stream->audio_fifo); ++ if (!buf) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: buffer_pool_alloc() failed!\n"), LOG_MODULE); ++ return -1; ++ } ++ ++ buf->type = BUF_CONTROL_RESET_TRACK_MAP; ++ ++ this->stream->audio_fifo->put(this->stream->audio_fifo, buf); ++ } ++ ++/* sched_yield(); */ ++ xine_usec_sleep(5000); ++ _n++; ++ } ++ ++ _t2 = _now(); ++ /* fprintf(stderr, "vdr: reset_audio: n: %d, %.1lf\n", _n, _t2 - _t1); */ ++ ++ xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1); ++ ++ _x_stream_info_reset(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE); ++ _x_meta_info_reset(this->stream, XINE_META_INFO_AUDIOCODEC); ++ ++ xine_set_param(this->stream, XINE_PARAM_IGNORE_AUDIO, 0); ++ } ++ } ++ break; ++ ++ case func_query_capabilities: ++ { ++ READ_DATA_OR_FAIL(query_capabilities, lprintf("got QUERYCAPABILITIES\n")); ++ ++ { ++ result_query_capabilities_t result_query_capabilities; ++ result_query_capabilities.header.func = data->header.func; ++ result_query_capabilities.header.len = sizeof (result_query_capabilities); ++ ++ result_query_capabilities.osd_max_num_windows = MAX_SHOWING; ++ result_query_capabilities.osd_palette_max_depth = 8; ++ result_query_capabilities.osd_palette_is_shared = 0; ++ result_query_capabilities.osd_supports_argb_layer = this->osd_supports_argb_layer; ++ result_query_capabilities.osd_supports_custom_extent = this->osd_supports_custom_extent; ++ ++ if (sizeof (result_query_capabilities) != vdr_write(this->fh_result, &result_query_capabilities, sizeof (result_query_capabilities))) ++ return -1; ++ } ++ } ++ break; ++ ++ default: ++ lprintf("unknown function: %d\n", this->cur_func); ++ } ++ ++ if (this->cur_size != this->cur_done) ++ { ++ off_t skip = this->cur_size - this->cur_done; ++ ++ lprintf("func: %d, skipping: %lld\n", this->cur_func, skip); ++ ++ while (skip > BUF_SIZE) ++ { ++ n = vdr_read_abort(this->stream, this->fh_control, this->seek_buf, BUF_SIZE); ++ if (n != BUF_SIZE) ++ return -1; ++ ++ skip -= BUF_SIZE; ++ } ++ ++ n = vdr_read_abort(this->stream, this->fh_control, this->seek_buf, skip); ++ if (n != skip) ++ return -1; ++ ++ this->cur_done = this->cur_size; ++ ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void *vdr_rpc_thread_loop(void *arg) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)arg; ++ int frontend_lock_failures = 0; ++ int failed = 0; ++ int was_startup_phase = this->startup_phase; ++ ++ while (!failed ++ && !this->rpc_thread_shutdown ++ && was_startup_phase == this->startup_phase) ++ { ++ struct timeval timeout; ++ fd_set rset; ++ ++ FD_ZERO(&rset); ++ FD_SET(this->fh_control, &rset); ++ ++ timeout.tv_sec = 0; ++ timeout.tv_usec = 50000; ++ ++ if (select(this->fh_control + 1, &rset, NULL, NULL, &timeout) > 0) ++ { ++ if (!_x_lock_frontend(this->stream, 100)) ++ { ++ if (++frontend_lock_failures > 50) ++ { ++ failed = 1; ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ LOG_MODULE ": locking frontend for rpc command execution failed, exiting ...\n"); ++ } ++ } ++ else ++ { ++ frontend_lock_failures = 0; ++ ++ if (_x_lock_port_rewiring(this->stream->xine, 100)) ++ { ++ if (vdr_execute_rpc_command(this) < 0) ++ { ++ failed = 1; ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ LOG_MODULE ": execution of rpc command %d (%s) failed, exiting ...\n", this->cur_func, ""); ++ } ++ ++ _x_unlock_port_rewiring(this->stream->xine); ++ } ++ ++ _x_unlock_frontend(this->stream); ++ } ++ } ++ } ++ ++ if (!failed && was_startup_phase) ++ return (void *)1; ++ ++ /* close control and result channel here to have vdr-xine initiate a disconnect for the above error case ... */ ++ close(this->fh_control); ++ this->fh_control = -1; ++ ++ close(this->fh_result); ++ this->fh_result = -1; ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ LOG_MODULE ": rpc thread done.\n"); ++ ++ pthread_mutex_lock(&this->rpc_thread_shutdown_lock); ++ this->rpc_thread_shutdown = -1; ++ pthread_cond_broadcast(&this->rpc_thread_shutdown_cond); ++ pthread_mutex_unlock(&this->rpc_thread_shutdown_lock); ++ ++ return 0; ++} ++ ++static int internal_write_event_key(vdr_input_plugin_t *this, uint32_t key) ++{ ++ event_key_t event; ++ event.header.func = func_key; ++ event.header.len = sizeof (event); ++ ++ event.key = key; ++ ++ if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event))) ++ return -1; ++ ++ return 0; ++} ++ ++static int internal_write_event_frame_size(vdr_input_plugin_t *this) ++{ ++ event_frame_size_t event; ++ event.header.func = func_frame_size; ++ event.header.len = sizeof (event); ++ ++ event.left = this->frame_size.x; ++ event.top = this->frame_size.y; ++ event.width = this->frame_size.w, ++ event.height = this->frame_size.h; ++ event.zoom_x = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_X); ++ event.zoom_y = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_Y); ++ ++ if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event))) ++ return -1; ++ ++ return 0; ++} ++ ++static int internal_write_event_play_external(vdr_input_plugin_t *this, uint32_t key) ++{ ++ event_play_external_t event; ++ event.header.func = func_play_external; ++ event.header.len = sizeof (event); ++ ++ event.key = key; ++ ++ if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event))) ++ return -1; ++ ++ return 0; ++} ++ ++static int internal_write_event_discontinuity(vdr_input_plugin_t *this, int32_t type) ++{ ++ event_discontinuity_t event; ++ event.header.func = func_discontinuity; ++ event.header.len = sizeof (event); ++ ++ event.type = type; ++ ++ if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event))) ++ return -1; ++ ++ return 0; ++} ++ ++static off_t vdr_plugin_read(input_plugin_t *this_gen, ++ char *buf_gen, off_t len) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; ++ uint8_t *buf = (uint8_t *)buf_gen; ++ off_t n, total; ++#ifdef LOG_READ ++ lprintf ("reading %lld bytes...\n", len); ++#endif ++ total=0; ++ if (this->curpos < this->preview_size) ++ { ++ n = this->preview_size - this->curpos; ++ if (n > (len - total)) ++ n = len - total; ++#ifdef LOG_READ ++ lprintf ("%lld bytes from preview (which has %lld bytes)\n", ++ n, this->preview_size); ++#endif ++ memcpy (&buf[total], &this->preview[this->curpos], n); ++ this->curpos += n; ++ total += n; ++ } ++ ++ if( (len-total) > 0 ) ++ { ++ int retries = 0; ++ do ++ { ++ n = vdr_read_abort (this->stream, this->fh, (char *)&buf[total], len-total); ++ if (0 == n) ++ lprintf("read 0, retries: %d\n", retries); ++ } ++ while (0 == n ++ && !this->stream_external ++ && _x_continue_stream_processing(this->stream) ++ && 200 > retries++); /* 200 * 50ms */ ++#ifdef LOG_READ ++ lprintf ("got %lld bytes (%lld/%lld bytes read)\n", ++ n,total,len); ++#endif ++ if (n < 0) ++ { ++ _x_message(this->stream, XINE_MSG_READ_ERROR, NULL); ++ return 0; ++ } ++ ++ this->curpos += n; ++ total += n; ++ } ++ ++ if (this->find_sync_point ++ && total == 6) ++ { ++ pthread_mutex_lock(&this->find_sync_point_lock); ++ ++ while (this->find_sync_point ++ && total == 6 ++ && buf[0] == 0x00 ++ && buf[1] == 0x00 ++ && buf[2] == 0x01) ++ { ++ int l, sp; ++ ++ if (buf[3] == 0xbe ++ && buf[4] == 0xff) ++ { ++/* fprintf(stderr, "------- seen sync point: %02x, waiting for: %02x\n", buf[5], this->find_sync_point); */ ++ if (buf[5] == this->find_sync_point) ++ { ++ this->find_sync_point = 0; ++ break; ++ } ++ } ++ ++ if ((buf[3] & 0xf0) != 0xe0 ++ && (buf[3] & 0xe0) != 0xc0 ++ && buf[3] != 0xbd ++ && buf[3] != 0xbe) ++ { ++ break; ++ } ++ ++ l = buf[4] * 256 + buf[5]; ++ if (l <= 0) ++ break; ++ ++ sp = this->find_sync_point; ++ this->find_sync_point = 0; ++ this_gen->seek(this_gen, l, SEEK_CUR); ++ total = this_gen->read(this_gen, buf, 6); ++ this->find_sync_point = sp; ++ } ++ ++ pthread_mutex_unlock(&this->find_sync_point_lock); ++ } ++ ++ return total; ++} ++ ++static buf_element_t *vdr_plugin_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, ++ off_t todo) ++{ ++ off_t total_bytes; ++ buf_element_t *buf = fifo->buffer_pool_alloc(fifo); ++ ++ buf->content = buf->mem; ++ buf->type = BUF_DEMUX_BLOCK; ++ ++ total_bytes = vdr_plugin_read(this_gen, (char *)buf->content, todo); ++ ++ if (total_bytes != todo) ++ { ++ buf->free_buffer(buf); ++ return NULL; ++ } ++ ++ buf->size = total_bytes; ++ ++ return buf; ++} ++ ++/* forward reference */ ++static off_t vdr_plugin_get_current_pos(input_plugin_t *this_gen); ++ ++static off_t vdr_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ ++ lprintf("seek %lld offset, %d origin...\n", ++ offset, origin); ++ ++ if ((origin == SEEK_CUR) && (offset >= 0)) ++ { ++ for ( ; ((int)offset) - BUF_SIZE > 0; offset -= BUF_SIZE) ++ { ++ if (!this_gen->read(this_gen, this->seek_buf, BUF_SIZE)) ++ return this->curpos; ++ } ++ ++ this_gen->read (this_gen, this->seek_buf, offset); ++ } ++ ++ if (origin == SEEK_SET) ++ { ++ if (offset < this->curpos) ++ { ++ if (this->curpos <= this->preview_size) ++ this->curpos = offset; ++ else ++ lprintf("cannot seek back! (%lld > %lld)\n", this->curpos, offset); ++ } ++ else ++ { ++ offset -= this->curpos; ++ ++ for ( ; ((int)offset) - BUF_SIZE > 0; offset -= BUF_SIZE) ++ { ++ if (!this_gen->read(this_gen, this->seek_buf, BUF_SIZE)) ++ return this->curpos; ++ } ++ ++ this_gen->read(this_gen, this->seek_buf, offset); ++ } ++ } ++ ++ return this->curpos; ++} ++ ++static off_t vdr_plugin_get_length(input_plugin_t *this_gen) ++{ ++ return 0; ++} ++ ++static uint32_t vdr_plugin_get_capabilities(input_plugin_t *this_gen) ++{ ++ return INPUT_CAP_PREVIEW; ++} ++ ++static uint32_t vdr_plugin_get_blocksize(input_plugin_t *this_gen) ++{ ++ return 0; ++} ++ ++static off_t vdr_plugin_get_current_pos(input_plugin_t *this_gen) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ ++ return this->curpos; ++} ++ ++static const char *vdr_plugin_get_mrl(input_plugin_t *this_gen) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ ++ return this->mrl; ++} ++ ++static void vdr_plugin_dispose(input_plugin_t *this_gen) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ int i; ++ ++ external_stream_stop(this); ++ ++ if (this->event_queue) ++ xine_event_dispose_queue(this->event_queue); ++ ++ if (this->rpc_thread) ++ { ++ struct timespec abstime; ++ int ms_to_time_out = 10000; ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: shutting down rpc thread (timeout: %d ms) ...\n"), LOG_MODULE, ms_to_time_out); ++ ++ pthread_mutex_lock(&this->rpc_thread_shutdown_lock); ++ ++ if (this->rpc_thread_shutdown > -1) ++ { ++ this->rpc_thread_shutdown = 1; ++ ++ { ++ struct timeval now; ++ gettimeofday(&now, 0); ++ ++ abstime.tv_sec = now.tv_sec + ms_to_time_out / 1000; ++ abstime.tv_nsec = now.tv_usec * 1000 + (ms_to_time_out % 1000) * 1e6; ++ ++ if (abstime.tv_nsec > 1e9) ++ { ++ abstime.tv_nsec -= 1e9; ++ abstime.tv_sec++; ++ } ++ } ++ ++ if (0 != pthread_cond_timedwait(&this->rpc_thread_shutdown_cond, &this->rpc_thread_shutdown_lock, &abstime)) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: cancelling rpc thread in function %d...\n"), LOG_MODULE, this->cur_func); ++ pthread_cancel(this->rpc_thread); ++ } ++ } ++ ++ pthread_mutex_unlock(&this->rpc_thread_shutdown_lock); ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: joining rpc thread ...\n"), LOG_MODULE); ++ pthread_join(this->rpc_thread, 0); ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: rpc thread joined.\n"), LOG_MODULE); ++ } ++ ++ pthread_cond_destroy(&this->rpc_thread_shutdown_cond); ++ pthread_mutex_destroy(&this->rpc_thread_shutdown_lock); ++ ++ if (this->metronom_thread) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: joining metronom thread ...\n"), LOG_MODULE); ++ ++ pthread_mutex_lock(&this->metronom_thread_call_lock); ++ ++ pthread_mutex_lock(&this->metronom_thread_lock); ++ this->metronom_thread_request = -1; ++ this->metronom_thread_reply = 0; ++ pthread_cond_broadcast(&this->metronom_thread_request_cond); ++/* ++ pthread_mutex_unlock(&this->metronom_thread_lock); ++ ++ pthread_mutex_lock(&this->metronom_thread_lock); ++ if (!this->metronom_thread_reply) ++*/ ++ pthread_cond_wait(&this->metronom_thread_reply_cond, &this->metronom_thread_lock); ++ pthread_mutex_unlock(&this->metronom_thread_lock); ++ ++ pthread_mutex_unlock(&this->metronom_thread_call_lock); ++ ++ pthread_join(this->metronom_thread, 0); ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: metronom thread joined.\n"), LOG_MODULE); ++ } ++ ++ pthread_mutex_destroy(&this->metronom_thread_lock); ++ pthread_cond_destroy(&this->metronom_thread_request_cond); ++ pthread_cond_destroy(&this->metronom_thread_reply_cond); ++ ++ pthread_mutex_destroy(&this->find_sync_point_lock); ++ pthread_mutex_destroy(&this->adjust_zoom_lock); ++ ++ if (this->fh_result != -1) ++ close(this->fh_result); ++ ++ if (this->fh_control != -1) ++ close(this->fh_control); ++ ++ if (this->fh_event != -1) ++ close(this->fh_event); ++ ++ for (i = 0; i < VDR_MAX_NUM_WINDOWS; i++) ++ { ++ if (0 == this->osd[ i ].window) ++ continue; ++ ++ xine_osd_hide(this->osd[ i ].window, 0); ++ xine_osd_free(this->osd[ i ].window); ++ ++ free(this->osd[ i ].argb_buffer); ++ } ++ ++ if (this->osd_buffer) ++ free(this->osd_buffer); ++ ++ if ((this->fh != STDIN_FILENO) && (this->fh != -1)) ++ close(this->fh); ++ ++ free(this->mrl); ++ ++ this->stream->metronom = this->metronom.stream_metronom; ++ this->metronom.stream_metronom = 0; ++ ++ vdr_vpts_offset_queue_purge(this); ++ pthread_cond_destroy(&this->vpts_offset_queue_changed_cond); ++ pthread_mutex_destroy(&this->vpts_offset_queue_lock); ++ ++ free(this); ++} ++ ++static int vdr_plugin_get_optional_data(input_plugin_t *this_gen, ++ void *data, int data_type) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ (void)this; ++ switch (data_type) ++ { ++ case INPUT_OPTIONAL_DATA_PREVIEW: ++ /* just fake what mpeg_pes demuxer expects */ ++ memcpy (data, "\x00\x00\x01\xe0\x00\x03\x80\x00\x00", 9); ++ return 9; ++ } ++ return INPUT_OPTIONAL_UNSUPPORTED; ++} ++ ++static inline const char *mrl_to_fifo (const char *mrl) ++{ ++ /* vdr://foo -> /foo */ ++ return mrl + 3 + strspn (mrl + 4, "/"); ++} ++ ++static inline const char *mrl_to_host (const char *mrl) ++{ ++ /* netvdr://host:port -> host:port */ ++ return strrchr (mrl, '/') + 1; ++} ++ ++static int vdr_plugin_open_fifo_mrl(input_plugin_t *this_gen) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ char *filename = (char *)mrl_to_fifo (this->mrl); ++ ++ if(!strcmp(filename, "/")) { ++ filename = (char *)VDR_ABS_FIFO_DIR "/stream"; ++ } ++ ++ filename = strdup(filename); ++ ++ _x_mrl_unescape (filename); ++ this->fh = open(filename, O_RDONLY | O_NONBLOCK); ++ ++ lprintf("filename '%s'\n", filename); ++ ++ if (this->fh == -1) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to open '%s' (%s)\n"), LOG_MODULE, ++ filename, ++ strerror(errno)); ++ free (filename); ++ return 0; ++ } ++ ++ { ++ struct pollfd poll_fh = { this->fh, POLLIN, 0 }; ++ ++ int r = poll(&poll_fh, 1, 300); ++ if (1 != r) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to open '%s' (%s)\n"), LOG_MODULE, ++ filename, ++ _("timeout expired during setup phase")); ++ free (filename); ++ return 0; ++ } ++ } ++ ++ fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0)); ++ ++ /* eat initial handshake byte */ ++ { ++ char b; ++ read(this->fh, &b, 1); ++ } ++ ++ { ++ char *filename_control = 0; ++ asprintf(&filename_control, "%s.control", filename); ++ ++ this->fh_control = open(filename_control, O_RDONLY); ++ ++ if (this->fh_control == -1) { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to open '%s' (%s)\n"), LOG_MODULE, ++ filename_control, ++ strerror(errno)); ++ ++ free(filename_control); ++ free (filename); ++ return 0; ++ } ++ ++ free(filename_control); ++ } ++ ++ { ++ char *filename_result = 0; ++ asprintf(&filename_result, "%s.result", filename); ++ ++ this->fh_result = open(filename_result, O_WRONLY); ++ ++ if (this->fh_result == -1) { ++ perror("failed"); ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to open '%s' (%s)\n"), LOG_MODULE, ++ filename_result, ++ strerror(errno)); ++ ++ free(filename_result); ++ free (filename); ++ return 0; ++ } ++ ++ free(filename_result); ++ } ++ ++ { ++ char *filename_event = 0; ++ asprintf(&filename_event, "%s.event", filename); ++ ++ this->fh_event = open(filename_event, O_WRONLY); ++ ++ if (this->fh_event == -1) { ++ perror("failed"); ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to open '%s' (%s)\n"), LOG_MODULE, ++ filename_event, ++ strerror(errno)); ++ ++ free(filename_event); ++ free (filename); ++ return 0; ++ } ++ ++ free(filename_event); ++ } ++ ++ free (filename); ++ return 1; ++} ++ ++static int vdr_plugin_open_socket(vdr_input_plugin_t *this, struct hostent *host, unsigned short port) ++{ ++ int fd; ++ struct sockaddr_in sain; ++ struct in_addr iaddr; ++ ++ if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to create socket for port %d (%s)\n"), LOG_MODULE, ++ port, strerror(errno)); ++ return -1; ++ } ++ ++ iaddr.s_addr = *((unsigned int *)host->h_addr_list[0]); ++ ++ sain.sin_port = htons(port); ++ sain.sin_family = AF_INET; ++ sain.sin_addr = iaddr; ++ ++ if (connect(fd, (struct sockaddr *)&sain, sizeof (sain)) < 0) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to connect to port %d (%s)\n"), LOG_MODULE, port, ++ strerror(errno)); ++ ++ return -1; ++ } ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: socket opening (port %d) successful, fd = %d\n"), LOG_MODULE, port, fd); ++ ++ return fd; ++} ++ ++static int vdr_plugin_open_sockets(vdr_input_plugin_t *this) ++{ ++ struct hostent *host; ++ char *mrl_host = strdup (mrl_to_host (this->mrl)); ++ char *mrl_port; ++ int port = 18701; ++ ++ mrl_port = strchr(mrl_host, '#'); ++ if (mrl_port) ++ *mrl_port = 0; /* strip off things like '#demux:mpeg_pes' */ ++ ++ _x_mrl_unescape (mrl_host); ++ ++ mrl_port = strchr(mrl_host, ':'); ++ if (mrl_port) ++ { ++ port = atoi(mrl_port + 1); ++ *mrl_port = 0; ++ } ++ ++ host = gethostbyname(mrl_host); ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: connecting to vdr.\n"), LOG_MODULE); ++ ++ if (!host) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: failed to resolve hostname '%s' (%s)\n"), LOG_MODULE, ++ mrl_host, ++ strerror(errno)); ++ free (mrl_host); ++ return 0; ++ } ++ free (mrl_host); ++ ++ if ((this->fh = vdr_plugin_open_socket(this, host, port + 0)) == -1) ++ return 0; ++ ++ fcntl(this->fh, F_SETFL, ~O_NONBLOCK & fcntl(this->fh, F_GETFL, 0)); ++ ++ if ((this->fh_control = vdr_plugin_open_socket(this, host, port + 1)) == -1) ++ return 0; ++ ++ if ((this->fh_result = vdr_plugin_open_socket(this, host, port + 2)) == -1) ++ return 0; ++ ++ if ((this->fh_event = vdr_plugin_open_socket(this, host, port + 3)) == -1) ++ return 0; ++ ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: connecting to all sockets (port %d .. %d) was successful.\n"), LOG_MODULE, port, port + 3); ++ ++ return 1; ++} ++ ++static int vdr_plugin_open_socket_mrl(input_plugin_t *this_gen) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ ++ lprintf("input_vdr: connecting to vdr-xine-server...\n"); ++ ++ if (!vdr_plugin_open_sockets(this)) ++ return 0; ++ ++ return 1; ++} ++ ++static void *vdr_metronom_thread_loop(void *arg) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)arg; ++ int run = 1; ++ ++ pthread_mutex_lock(&this->metronom_thread_lock); ++ ++ while (run) ++ { ++ if (this->metronom_thread_request == 0) ++ pthread_cond_wait(&this->metronom_thread_request_cond, &this->metronom_thread_lock); ++ ++ if (this->metronom_thread_request == -1) ++ run = 0; ++ else ++ this->metronom.metronom.handle_audio_discontinuity(&this->metronom.metronom, DISC_ABSOLUTE, this->metronom_thread_request); ++ ++ this->metronom_thread_request = 0; ++ this->metronom_thread_reply = 1; ++ pthread_cond_broadcast(&this->metronom_thread_reply_cond); ++ } ++ ++ pthread_mutex_unlock(&this->metronom_thread_lock); ++ ++ return 0; ++} ++ ++static int vdr_plugin_open(input_plugin_t *this_gen) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; ++ ++ lprintf("trying to open '%s'...\n", this->mrl); ++ ++ if (this->fh == -1) ++ { ++ int err = 0; ++ ++ if (!strncasecmp(&this->mrl[0], "vdr:/", 5)) ++ { ++ if (!vdr_plugin_open_fifo_mrl(this_gen)) ++ return 0; ++ } ++ else if (!strncasecmp(&this->mrl[0], "netvdr:/", 8)) ++ { ++ if (!vdr_plugin_open_socket_mrl(this_gen)) ++ return 0; ++ } ++ else ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: MRL (%s) invalid! MRL should start with vdr://path/to/fifo/stream or netvdr://host:port where ':port' is optional.\n"), LOG_MODULE, ++ strerror(err)); ++ return 0; ++ } ++ ++ if ((err = pthread_create(&this->metronom_thread, NULL, ++ vdr_metronom_thread_loop, (void *)this)) != 0) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: can't create new thread (%s)\n"), LOG_MODULE, ++ strerror(err)); ++ ++ return 0; ++ } ++ ++ this->rpc_thread_shutdown = 0; ++ ++ /* let this thread handle rpc commands in startup phase */ ++ this->startup_phase = 1; ++ if (0 == vdr_rpc_thread_loop(this)) ++ return 0; ++/* fprintf(stderr, "####################################################\n"); */ ++ if ((err = pthread_create(&this->rpc_thread, NULL, ++ vdr_rpc_thread_loop, (void *)this)) != 0) ++ { ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: can't create new thread (%s)\n"), LOG_MODULE, ++ strerror(err)); ++ ++ return 0; ++ } ++ } ++ ++ /* ++ * mrl accepted and opened successfully at this point ++ * ++ * => create plugin instance ++ */ ++ ++ this->preview = NULL; ++ this->preview_size = 0; ++ this->curpos = 0; ++ ++ return 1; ++} ++ ++static void event_handler(void *user_data, const xine_event_t *event) ++{ ++ vdr_input_plugin_t *this = (vdr_input_plugin_t *)user_data; ++ uint32_t key = key_none; ++ ++ lprintf("eventHandler(): event->type: %d\n", event->type); ++ ++ if (XINE_EVENT_VDR_FRAMESIZECHANGED == event->type) ++ { ++ memcpy(&this->frame_size, event->data, event->data_length); ++ ++ if (0 != internal_write_event_frame_size(this)) ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno)); ++ ++ adjust_zoom(this); ++ return; ++ } ++ ++ if (XINE_EVENT_VDR_DISCONTINUITY == event->type) ++ { ++ if (0 != internal_write_event_discontinuity(this, event->data_length)) ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno)); ++ ++ return; ++ } ++ ++ if (XINE_EVENT_VDR_PLUGINSTARTED == event->type) ++ { ++ if (0 == event->data_length) /* vdr_video */ ++ { ++ xine_event_t event; ++ ++ event.type = XINE_EVENT_VDR_TRICKSPEEDMODE; ++ event.data = 0; ++ event.data_length = 0; /* this->trick_speed_mode; */ ++ ++ xine_event_send(this->stream, &event); ++ } ++ else if (1 == event->data_length) /* vdr_audio */ ++ { ++ xine_event_t event; ++ vdr_select_audio_data_t event_data; ++ ++ event_data.channels = this->audio_channels; ++ ++ event.type = XINE_EVENT_VDR_SELECTAUDIO; ++ event.data = &event_data; ++ event.data_length = sizeof (event_data); ++ ++ xine_event_send(this->stream, &event); ++ } ++ else ++ { ++ fprintf(stderr, "input_vdr: illegal XINE_EVENT_VDR_PLUGINSTARTED: %d\n", event->data_length); ++ } ++ ++ return; ++ } ++ ++ switch (event->type) ++ { ++ case XINE_EVENT_INPUT_UP: key = key_up; break; ++ case XINE_EVENT_INPUT_DOWN: key = key_down; break; ++ case XINE_EVENT_INPUT_LEFT: key = key_left; break; ++ case XINE_EVENT_INPUT_RIGHT: key = key_right; break; ++ case XINE_EVENT_INPUT_SELECT: key = key_ok; break; ++ case XINE_EVENT_VDR_BACK: key = key_back; break; ++ case XINE_EVENT_VDR_CHANNELPLUS: key = key_channel_plus; break; ++ case XINE_EVENT_VDR_CHANNELMINUS: key = key_channel_minus; break; ++ case XINE_EVENT_VDR_RED: key = key_red; break; ++ case XINE_EVENT_VDR_GREEN: key = key_green; break; ++ case XINE_EVENT_VDR_YELLOW: key = key_yellow; break; ++ case XINE_EVENT_VDR_BLUE: key = key_blue; break; ++ case XINE_EVENT_VDR_PLAY: key = key_play; break; ++ case XINE_EVENT_VDR_PAUSE: key = key_pause; break; ++ case XINE_EVENT_VDR_STOP: key = key_stop; break; ++ case XINE_EVENT_VDR_RECORD: key = key_record; break; ++ case XINE_EVENT_VDR_FASTFWD: key = key_fast_fwd; break; ++ case XINE_EVENT_VDR_FASTREW: key = key_fast_rew; break; ++ case XINE_EVENT_VDR_POWER: key = key_power; break; ++ case XINE_EVENT_VDR_SCHEDULE: key = key_schedule; break; ++ case XINE_EVENT_VDR_CHANNELS: key = key_channels; break; ++ case XINE_EVENT_VDR_TIMERS: key = key_timers; break; ++ case XINE_EVENT_VDR_RECORDINGS: key = key_recordings; break; ++ case XINE_EVENT_INPUT_MENU1: key = key_menu; break; ++ case XINE_EVENT_VDR_SETUP: key = key_setup; break; ++ case XINE_EVENT_VDR_COMMANDS: key = key_commands; break; ++ case XINE_EVENT_INPUT_NUMBER_0: key = key_0; break; ++ case XINE_EVENT_INPUT_NUMBER_1: key = key_1; break; ++ case XINE_EVENT_INPUT_NUMBER_2: key = key_2; break; ++ case XINE_EVENT_INPUT_NUMBER_3: key = key_3; break; ++ case XINE_EVENT_INPUT_NUMBER_4: key = key_4; break; ++ case XINE_EVENT_INPUT_NUMBER_5: key = key_5; break; ++ case XINE_EVENT_INPUT_NUMBER_6: key = key_6; break; ++ case XINE_EVENT_INPUT_NUMBER_7: key = key_7; break; ++ case XINE_EVENT_INPUT_NUMBER_8: key = key_8; break; ++ case XINE_EVENT_INPUT_NUMBER_9: key = key_9; break; ++ case XINE_EVENT_VDR_USER1: key = key_user1; break; ++ case XINE_EVENT_VDR_USER2: key = key_user2; break; ++ case XINE_EVENT_VDR_USER3: key = key_user3; break; ++ case XINE_EVENT_VDR_USER4: key = key_user4; break; ++ case XINE_EVENT_VDR_USER5: key = key_user5; break; ++ case XINE_EVENT_VDR_USER6: key = key_user6; break; ++ case XINE_EVENT_VDR_USER7: key = key_user7; break; ++ case XINE_EVENT_VDR_USER8: key = key_user8; break; ++ case XINE_EVENT_VDR_USER9: key = key_user9; break; ++ case XINE_EVENT_VDR_VOLPLUS: key = key_volume_plus; break; ++ case XINE_EVENT_VDR_VOLMINUS: key = key_volume_minus; break; ++ case XINE_EVENT_VDR_MUTE: key = key_mute; break; ++ case XINE_EVENT_VDR_AUDIO: key = key_audio; break; ++ case XINE_EVENT_VDR_INFO: key = key_info; break; ++ case XINE_EVENT_VDR_CHANNELPREVIOUS: key = key_channel_previous; break; ++ case XINE_EVENT_INPUT_NEXT: key = key_next; break; ++ case XINE_EVENT_INPUT_PREVIOUS: key = key_previous; break; ++ case XINE_EVENT_VDR_SUBTITLES: key = key_subtitles; break; ++ default: ++ return; ++ } ++ ++ if (0 != internal_write_event_key(this, key)) ++ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, ++ _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno)); ++} ++ ++ ++static int64_t vdr_vpts_offset_queue_change_begin(vdr_input_plugin_t *this, int type) ++{ ++ pthread_mutex_lock(&this->vpts_offset_queue_lock); ++ this->vpts_offset_queue_changes++; ++ pthread_mutex_unlock(&this->vpts_offset_queue_lock); ++ ++ return this->metronom.metronom.get_option(&this->metronom.metronom, METRONOM_VPTS_OFFSET); ++} ++ ++static void vdr_vpts_offset_queue_change_end(vdr_input_plugin_t *this, int type, int64_t disc_off, int64_t vpts_offset) ++{ ++ pthread_mutex_lock(&this->vpts_offset_queue_lock); ++ ++if(0) ++ { ++fprintf(stderr, "A ---------------------------------------------\n"); ++ vdr_vpts_offset_t *p = this->vpts_offset_queue; ++ while (p) ++ { ++ fprintf(stderr, "A now: %12"PRId64", vpts: %12"PRId64", offset: %12"PRId64"\n", xine_get_current_vpts(this->stream), p->vpts, p->offset); ++ p = p->next; ++ } ++fprintf(stderr, "A =============================================\n"); ++ } ++ ++ if (type == DISC_ABSOLUTE) ++ { ++ int64_t vpts = this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET) + disc_off; ++ ++ if (!this->vpts_offset_queue ++ || this->vpts_offset_queue_tail->vpts < vpts) ++ { ++ vdr_vpts_offset_t *curr = (vdr_vpts_offset_t *)calloc(1, sizeof (vdr_vpts_offset_t)); ++ curr->vpts = vpts; ++ curr->offset = vpts_offset; ++ ++ if (!this->vpts_offset_queue) ++ this->vpts_offset_queue = this->vpts_offset_queue_tail = curr; ++ else ++ { ++ this->vpts_offset_queue_tail->next = curr; ++ this->vpts_offset_queue_tail = curr; ++ } ++ } ++ } ++ else ++ vdr_vpts_offset_queue_purge(this); ++ ++if(0) ++ { ++fprintf(stderr, "B ---------------------------------------------\n"); ++ vdr_vpts_offset_t *p = this->vpts_offset_queue; ++ while (p) ++ { ++ fprintf(stderr, "B now: %12"PRId64", vpts: %12"PRId64", offset: %12"PRId64"\n", xine_get_current_vpts(this->stream), p->vpts, p->offset); ++ p = p->next; ++ } ++fprintf(stderr, "B =============================================\n"); ++ } ++ ++ this->vpts_offset_queue_changes--; ++ pthread_cond_broadcast(&this->vpts_offset_queue_changed_cond); ++ ++ this->last_disc_type = type; ++ ++ pthread_mutex_unlock(&this->vpts_offset_queue_lock); ++ ++ if (!this->trick_speed_mode) ++ { ++ xine_event_t event; ++ ++ event.type = XINE_EVENT_VDR_DISCONTINUITY; ++ event.data = 0; ++ event.data_length = type; ++ ++ xine_event_send(this->stream, &event); ++ } ++} ++ ++static void vdr_metronom_handle_audio_discontinuity(metronom_t *self, int type, int64_t disc_off) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ int64_t vpts_offset = vdr_vpts_offset_queue_change_begin(this->input, type); ++/* fprintf(stderr, "had A: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */ ++ this->stream_metronom->handle_audio_discontinuity(this->stream_metronom, type, disc_off); ++/* fprintf(stderr, "had B: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */ ++ vdr_vpts_offset_queue_change_end(this->input, type, disc_off, vpts_offset); ++} ++ ++static void vdr_metronom_handle_video_discontinuity(metronom_t *self, int type, int64_t disc_off) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ int64_t vpts_offset = vdr_vpts_offset_queue_change_begin(this->input, type); ++/* fprintf(stderr, "hvd A: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */ ++ this->stream_metronom->handle_video_discontinuity(this->stream_metronom, type, disc_off); ++/* fprintf(stderr, "hvd B: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */ ++ vdr_vpts_offset_queue_change_end(this->input, type, disc_off, vpts_offset); ++} ++ ++static void vdr_metronom_got_video_frame(metronom_t *self, vo_frame_t *frame) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ ++ if (this->input->trick_speed_mode && frame->pts) ++ { ++ pthread_mutex_lock(&this->input->metronom_thread_call_lock); ++ ++ pthread_mutex_lock(&this->input->metronom_thread_lock); ++ this->input->metronom_thread_request = frame->pts; ++ this->input->metronom_thread_reply = 0; ++ pthread_cond_broadcast(&this->input->metronom_thread_request_cond); ++ pthread_mutex_unlock(&this->input->metronom_thread_lock); ++ ++ vdr_metronom_handle_video_discontinuity(self, DISC_ABSOLUTE, frame->pts); ++ ++ pthread_mutex_lock(&this->input->metronom_thread_lock); ++ if (!this->input->metronom_thread_reply) ++ pthread_cond_wait(&this->input->metronom_thread_reply_cond, &this->input->metronom_thread_lock); ++ pthread_mutex_unlock(&this->input->metronom_thread_lock); ++ ++ pthread_mutex_unlock(&this->input->metronom_thread_call_lock); ++ } ++ ++ this->stream_metronom->got_video_frame(this->stream_metronom, frame); ++ ++ if (this->input->trick_speed_mode && frame->pts) ++ { ++/* fprintf(stderr, "vpts: %12ld, pts: %12ld, offset: %12ld\n", frame->vpts, frame->pts, this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */ ++ } ++} ++ ++static int64_t vdr_metronom_got_audio_samples(metronom_t *self, int64_t pts, int nsamples) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ return this->stream_metronom->got_audio_samples(this->stream_metronom, pts, nsamples); ++} ++ ++static int64_t vdr_metronom_got_spu_packet(metronom_t *self, int64_t pts) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ return this->stream_metronom->got_spu_packet(this->stream_metronom, pts); ++} ++ ++static void vdr_metronom_set_audio_rate(metronom_t *self, int64_t pts_per_smpls) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ this->stream_metronom->set_audio_rate(this->stream_metronom, pts_per_smpls); ++} ++ ++static void vdr_metronom_set_option(metronom_t *self, int option, int64_t value) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ this->stream_metronom->set_option(this->stream_metronom, option, value); ++} ++ ++static int64_t vdr_metronom_get_option(metronom_t *self, int option) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ return this->stream_metronom->get_option(this->stream_metronom, option); ++} ++ ++static void vdr_metronom_set_master(metronom_t *self, metronom_t *master) ++{ ++ vdr_metronom_t *this = (vdr_metronom_t *)self; ++ this->stream_metronom->set_master(this->stream_metronom, master); ++} ++ ++static void vdr_metronom_exit(metronom_t *self) ++{ ++ _x_abort(); ++} ++ ++ ++static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_stream_t *stream, ++ const char *data) ++{ ++ vdr_input_plugin_t *this; ++ char *mrl = strdup(data); ++ ++ if (!strncasecmp(mrl, "vdr:/", 5)) ++ lprintf("filename '%s'\n", mrl_to_path (mrl)); ++ else if (!strncasecmp(mrl, "netvdr:/", 5)) ++ lprintf("host '%s'\n", mrl_to_socket (mrl)); ++ else ++ { ++ free(mrl); ++ return NULL; ++ } ++ ++ /* ++ * mrl accepted and opened successfully at this point ++ * ++ * => create plugin instance ++ */ ++ ++ this = (vdr_input_plugin_t *)xine_xmalloc(sizeof (vdr_input_plugin_t)); ++ ++ this->stream = stream; ++ this->curpos = 0; ++ this->mrl = mrl; ++ this->fh = -1; ++ this->fh_control = -1; ++ this->fh_result = -1; ++ this->fh_event = -1; ++ ++ this->input_plugin.open = vdr_plugin_open; ++ this->input_plugin.get_capabilities = vdr_plugin_get_capabilities; ++ this->input_plugin.read = vdr_plugin_read; ++ this->input_plugin.read_block = vdr_plugin_read_block; ++ this->input_plugin.seek = vdr_plugin_seek; ++ this->input_plugin.get_current_pos = vdr_plugin_get_current_pos; ++ this->input_plugin.get_length = vdr_plugin_get_length; ++ this->input_plugin.get_blocksize = vdr_plugin_get_blocksize; ++ this->input_plugin.get_mrl = vdr_plugin_get_mrl; ++ this->input_plugin.dispose = vdr_plugin_dispose; ++ this->input_plugin.get_optional_data = vdr_plugin_get_optional_data; ++ this->input_plugin.input_class = cls_gen; ++ ++ this->cur_func = func_unknown; ++ this->cur_size = 0; ++ this->cur_done = 0; ++ ++ memset(this->osd, 0, sizeof (this->osd)); ++ ++ { ++ xine_osd_t *osd = xine_osd_new(this->stream, 0, 0, 16, 16); ++ uint32_t caps = xine_osd_get_capabilities(osd); ++ xine_osd_free(osd); ++ ++#ifdef XINE_OSD_CAP_ARGB_LAYER ++ this->osd_supports_argb_layer = !!(caps & XINE_OSD_CAP_ARGB_LAYER); ++#endif ++#ifdef XINE_OSD_CAP_CUSTOM_EXTENT ++ this->osd_supports_custom_extent = !!(caps & XINE_OSD_CAP_CUSTOM_EXTENT); ++#endif ++ } ++ ++ this->osd_buffer = 0; ++ this->osd_buffer_size = 0; ++ this->osd_unscaled_blending = 0; ++ this->trick_speed_mode = 0; ++ this->audio_channels = 0; ++ this->mute_mode = XINE_VDR_MUTE_SIMULATE; ++ this->volume_mode = XINE_VDR_VOLUME_CHANGE_HW; ++ this->last_volume = -1; ++ this->frame_size.x = 0; ++ this->frame_size.y = 0; ++ this->frame_size.w = 0; ++ this->frame_size.h = 0; ++ this->frame_size.r = 0; ++ ++ this->stream_external = 0; ++ this->event_queue_external = 0; ++ ++ pthread_mutex_init(&this->rpc_thread_shutdown_lock, 0); ++ pthread_cond_init(&this->rpc_thread_shutdown_cond, 0); ++ ++ pthread_mutex_init(&this->metronom_thread_lock, 0); ++ pthread_cond_init(&this->metronom_thread_request_cond, 0); ++ pthread_cond_init(&this->metronom_thread_reply_cond, 0); ++ pthread_mutex_init(&this->metronom_thread_call_lock, 0); ++ ++ pthread_mutex_init(&this->find_sync_point_lock, 0); ++ pthread_mutex_init(&this->adjust_zoom_lock, 0); ++ this->image4_3_zoom_x = 0; ++ this->image4_3_zoom_y = 0; ++ this->image16_9_zoom_x = 0; ++ this->image16_9_zoom_y = 0; ++ ++ this->event_queue = xine_event_new_queue(this->stream); ++ if (this->event_queue) ++ xine_event_create_listener_thread(this->event_queue, event_handler, this); ++ ++ this->metronom.input = this; ++ this->metronom.metronom.set_audio_rate = vdr_metronom_set_audio_rate; ++ this->metronom.metronom.got_video_frame = vdr_metronom_got_video_frame; ++ this->metronom.metronom.got_audio_samples = vdr_metronom_got_audio_samples; ++ this->metronom.metronom.got_spu_packet = vdr_metronom_got_spu_packet; ++ this->metronom.metronom.handle_audio_discontinuity = vdr_metronom_handle_audio_discontinuity; ++ this->metronom.metronom.handle_video_discontinuity = vdr_metronom_handle_video_discontinuity; ++ this->metronom.metronom.set_option = vdr_metronom_set_option; ++ this->metronom.metronom.get_option = vdr_metronom_get_option; ++ this->metronom.metronom.set_master = vdr_metronom_set_master; ++ this->metronom.metronom.exit = vdr_metronom_exit; ++ ++ this->metronom.stream_metronom = stream->metronom; ++ stream->metronom = &this->metronom.metronom; ++ ++ pthread_mutex_init(&this->vpts_offset_queue_lock, 0); ++ pthread_cond_init(&this->vpts_offset_queue_changed_cond, 0); ++ ++ return &this->input_plugin; ++} ++ ++/* ++ * vdr input plugin class stuff ++ */ ++ ++static const char *vdr_class_get_description(input_class_t *this_gen) ++{ ++ return _("VDR display device plugin"); ++} ++ ++static const char *vdr_class_get_identifier (input_class_t *this_gen) ++{ ++ return "VDR"; ++} ++ ++static void vdr_class_dispose (input_class_t *this_gen) ++{ ++ vdr_input_class_t *this = (vdr_input_class_t *)this_gen; ++ ++ free(this); ++} ++ ++static char **vdr_class_get_autoplay_list(input_class_t *this_gen, ++ int *num_files) ++{ ++ vdr_input_class_t *class = (vdr_input_class_t *)this_gen; ++ ++ *num_files = 1; ++ return (char **)class->mrls; ++} ++ ++void *vdr_input_init_plugin(xine_t *xine, void *data) ++{ ++ vdr_input_class_t *this; ++ ++ lprintf("init_class\n"); ++ ++ this = (vdr_input_class_t *)xine_xmalloc(sizeof (vdr_input_class_t)); ++ ++ this->xine = xine; ++ ++ this->mrls[ 0 ] = "vdr:/" VDR_ABS_FIFO_DIR "/stream#demux:mpeg_pes"; ++ this->mrls[ 1 ] = 0; ++ ++ this->input_class.get_instance = vdr_class_get_instance; ++ this->input_class.get_identifier = vdr_class_get_identifier; ++ this->input_class.get_description = vdr_class_get_description; ++ this->input_class.get_dir = NULL; ++ this->input_class.get_autoplay_list = vdr_class_get_autoplay_list; ++ this->input_class.dispose = vdr_class_dispose; ++ this->input_class.eject_media = NULL; ++ ++ return this; ++} +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/Makefile.am +@@ -0,0 +1,13 @@ ++include $(top_srcdir)/misc/Makefile.common ++ ++AM_CFLAGS = -D_LARGEFILE64_SOURCE ++ ++xineplug_LTLIBRARIES = \ ++ xineplug_vdr.la ++ ++xineplug_vdr_la_SOURCES = combined_vdr.c input_vdr.c post_vdr_video.c post_vdr_audio.c ++xineplug_vdr_la_LIBADD = $(XINE_LIB) ++xineplug_vdr_la_LDFLAGS = -avoid-version -module @IMPURE_TEXT_LDFLAGS@ ++ ++xineinclude_HEADERS = vdr.h ++noinst_HEADERS = combined_vdr.h +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/combined_vdr.h +@@ -0,0 +1,92 @@ ++/* ++ * Copyright (C) 2000-2004 the xine project ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ */ ++ ++#ifndef __COMBINED_VDR_H ++#define __COMBINED_VDR_H ++ ++ ++ ++typedef struct vdr_set_video_window_data_s { ++ int32_t x; ++ int32_t y; ++ int32_t w; ++ int32_t h; ++ int32_t w_ref; ++ int32_t h_ref; ++ ++} vdr_set_video_window_data_t; ++ ++ ++ ++typedef struct vdr_frame_size_changed_data_s { ++ int32_t x; ++ int32_t y; ++ int32_t w; ++ int32_t h; ++ double r; ++ ++} vdr_frame_size_changed_data_t; ++ ++ ++ ++typedef struct vdr_select_audio_data_s { ++ uint8_t channels; ++ ++} vdr_select_audio_data_t; ++ ++ ++ ++inline static int vdr_is_vdr_stream(xine_stream_t *stream) ++{ ++ if (!stream ++ || !stream->input_plugin ++ || !stream->input_plugin->input_class) ++ { ++ return 0; ++ } ++ ++ { ++ input_class_t *input_class = stream->input_plugin->input_class; ++ ++ if (input_class->get_identifier) ++ { ++ const char *identifier = input_class->get_identifier(input_class); ++ if (identifier ++ && 0 == strcmp(identifier, "VDR")) ++ { ++ return 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++ ++ ++/* plugin class initialization function */ ++void *vdr_input_init_plugin(xine_t *xine, void *data); ++void *vdr_video_init_plugin(xine_t *xine, void *data); ++void *vdr_audio_init_plugin(xine_t *xine, void *data); ++ ++ ++ ++#endif /* __COMBINED_VDR_H */ ++ +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/combined_vdr.c +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2000-2004 the xine project ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ */ ++ ++/* ++ * plugins for VDR ++ */ ++ ++#include "xine_internal.h" ++#include "post.h" ++#include "combined_vdr.h" ++ ++ ++ ++static const post_info_t vdr_video_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; ++static const post_info_t vdr_audio_special_info = { XINE_POST_TYPE_AUDIO_FILTER }; ++ ++/* exported plugin catalog entry */ ++const plugin_info_t xine_plugin_info[] EXPORTED = ++{ ++ /* type , API, "name" , version , special_info , init_function */ ++ { PLUGIN_INPUT, 17, "VDR" , XINE_VERSION_CODE, NULL , &vdr_input_init_plugin }, ++ { PLUGIN_POST , 9, "vdr" , XINE_VERSION_CODE, &vdr_video_special_info, &vdr_video_init_plugin }, ++ { PLUGIN_POST , 9, "vdr_video", XINE_VERSION_CODE, &vdr_video_special_info, &vdr_video_init_plugin }, ++ { PLUGIN_POST , 9, "vdr_audio", XINE_VERSION_CODE, &vdr_audio_special_info, &vdr_audio_init_plugin }, ++ { PLUGIN_NONE , 0, "" , 0 , NULL , NULL } ++}; ++ +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/post_vdr_video.c +@@ -0,0 +1,502 @@ ++/* ++ * Copyright (C) 2000-2004 the xine project ++ * ++ * This file is part of xine, a free video player. ++ * ++ * xine is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * xine is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA ++ */ ++ ++/* ++ * frame scaler plugin for VDR ++ */ ++ ++#define LOG_MODULE "vdr_video" ++/* ++#define LOG ++#define LOG_VERBOSE ++*/ ++ ++#include "xine_internal.h" ++#include "post.h" ++#include "combined_vdr.h" ++ ++ ++ ++typedef struct vdr_video_post_plugin_s ++{ ++ post_plugin_t post_plugin; ++ ++ xine_event_queue_t *event_queue; ++ xine_stream_t *vdr_stream; ++ ++ int8_t trick_speed_mode; ++ int8_t enabled; ++ ++ int32_t x; ++ int32_t y; ++ int32_t w; ++ int32_t h; ++ int32_t w_ref; ++ int32_t h_ref; ++ ++ int32_t old_frame_left; ++ int32_t old_frame_top; ++ int32_t old_frame_width; ++ int32_t old_frame_height; ++ double old_frame_ratio; ++ ++} ++vdr_video_post_plugin_t; ++ ++ ++static void vdr_video_set_video_window(vdr_video_post_plugin_t *this, int32_t x, int32_t y, int32_t w, int32_t h, int32_t w_ref, int32_t h_ref) ++{ ++ this->enabled = 0; ++ ++ this->x = x; ++ this->y = y; ++ this->w = w; ++ this->h = h; ++ this->w_ref = w_ref; ++ this->h_ref = h_ref; ++ ++ if (w != w_ref || h != h_ref) ++ this->enabled = 1; ++} ++ ++ ++/* plugin class functions */ ++static post_plugin_t *vdr_video_open_plugin(post_class_t *class_gen, int inputs, ++ xine_audio_port_t **audio_target, ++ xine_video_port_t **video_target); ++static char *vdr_video_get_identifier(post_class_t *class_gen); ++static char *vdr_video_get_description(post_class_t *class_gen); ++static void vdr_video_class_dispose(post_class_t *class_gen); ++ ++/* plugin instance functions */ ++static void vdr_video_dispose(post_plugin_t *this_gen); ++ ++/* route preprocessing functions check */ ++static int vdr_video_route_preprocessing_procs(post_video_port_t *port, vo_frame_t *frame); ++ ++/* replaced vo_frame functions */ ++static int vdr_video_draw(vo_frame_t *frame, xine_stream_t *stream); ++ ++ ++void *vdr_video_init_plugin(xine_t *xine, void *data) ++{ ++ post_class_t *class = (post_class_t *)xine_xmalloc(sizeof (post_class_t)); ++ ++ if (!class) ++ return NULL; ++ ++ class->open_plugin = vdr_video_open_plugin; ++ class->get_identifier = vdr_video_get_identifier; ++ class->get_description = vdr_video_get_description; ++ class->dispose = vdr_video_class_dispose; ++ ++ return class; ++} ++ ++static post_plugin_t *vdr_video_open_plugin(post_class_t *class_gen, int inputs, ++ xine_audio_port_t **audio_target, ++ xine_video_port_t **video_target) ++{ ++ vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)xine_xmalloc(sizeof (vdr_video_post_plugin_t)); ++ post_in_t *input; ++ post_out_t *output; ++ post_video_port_t *port; ++ ++ if (!this || !video_target || !video_target[ 0 ]) ++ { ++ free(this); ++ return NULL; ++ } ++ ++ _x_post_init(&this->post_plugin, 0, 1); ++ this->post_plugin.dispose = vdr_video_dispose; ++ ++ port = _x_post_intercept_video_port(&this->post_plugin, video_target[ 0 ], &input, &output); ++ port->route_preprocessing_procs = vdr_video_route_preprocessing_procs; ++ port->new_frame->draw = vdr_video_draw; ++ this->post_plugin.xine_post.video_input[ 0 ] = &port->new_port; ++ ++ this->enabled = 0; ++ this->vdr_stream = 0; ++ this->event_queue = 0; ++ this->old_frame_left = 0; ++ this->old_frame_top = 0; ++ this->old_frame_width = 0; ++ this->old_frame_height = 0; ++ this->old_frame_ratio = 0; ++ this->trick_speed_mode = 0; ++ ++ return &this->post_plugin; ++} ++ ++static char *vdr_video_get_identifier(post_class_t *class_gen) ++{ ++ return "vdr"; ++} ++ ++static char *vdr_video_get_description(post_class_t *class_gen) ++{ ++ return "modifies every video frame as requested by VDR"; ++} ++ ++static void vdr_video_class_dispose(post_class_t *class_gen) ++{ ++ free(class_gen); ++} ++ ++ ++static void vdr_video_dispose(post_plugin_t *this_gen) ++{ ++ if (_x_post_dispose(this_gen)) ++ { ++ vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)this_gen; ++ ++ if (this->vdr_stream) ++ { ++ xine_event_t event; ++ vdr_frame_size_changed_data_t event_data; ++ ++ event_data.x = 0; ++ event_data.y = 0; ++ event_data.w = 0; ++ event_data.h = 0; ++ ++ event.type = XINE_EVENT_VDR_FRAMESIZECHANGED; ++ event.data = &event_data; ++ event.data_length = sizeof (event_data); ++ ++ xine_event_send(this->vdr_stream, &event); ++ ++ xine_event_dispose_queue(this->event_queue); ++ } ++ ++ free(this_gen); ++ } ++} ++ ++static int vdr_video_route_preprocessing_procs(post_video_port_t *port, vo_frame_t *frame) ++{ ++ vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)port->post; ++ return !this->enabled ++ || (frame->format != XINE_IMGFMT_YUY2 ++ && frame->format != XINE_IMGFMT_YV12); ++} ++ ++ ++static inline void vdr_video_scale(uint8_t *src, uint8_t *dst, int y_inc, int x_inc, int w_dst, int h_dst, int x, int y, int w, int h, int w_ref, int h_ref, int init) ++{ ++ int x0 = x * w_dst / w_ref; ++ int y0 = y * h_dst / h_ref; ++ ++ int x1 = ((x + w) * w_dst - 1 + w_ref) / w_ref; ++ int y1 = ((y + h) * h_dst - 1 + h_ref) / h_ref; ++ ++ int dx = x1 - x0; ++ int dy = y1 - y0; ++ ++ int yy, xx; ++ ++ int dy2 = dy + dy; ++ int h_dst2 = h_dst + h_dst; ++ int y_eps = h_dst - dy2; ++ ++ int dx2 = dx + dx; ++ int w_dst2 = w_dst + w_dst; ++ int x_eps0 = w_dst - dx2; ++ ++ for (yy = 0; yy < y0; yy++) ++ { ++ uint8_t *dst0 = dst; ++ ++ for (xx = 0; xx < w_dst; xx++) ++ { ++ *dst0 = init; ++ dst0 += x_inc; ++ } ++ ++ dst += y_inc; ++ } ++ ++ for (yy = y0; yy < y1; yy++) ++ { ++ uint8_t *dst0 = dst; ++ uint8_t *src0 = src; ++ ++ int x_eps = x_eps0; ++ ++ for (xx = 0; xx < x0; xx++) ++ { ++ *dst0 = init; ++ dst0 += x_inc; ++ } ++ ++ for (xx = x0; xx < x1; xx++) ++ { ++ *dst0 = *src0; ++ dst0 += x_inc; ++ ++ x_eps += w_dst2; ++ while (x_eps >= 0) ++ { ++ src0 += x_inc; ++ x_eps -= dx2; ++ } ++ } ++ ++ for (xx = x1; xx < w_dst; xx++) ++ { ++ *dst0 = init; ++ dst0 += x_inc; ++ } ++ ++ dst += y_inc; ++ ++ y_eps += h_dst2; ++ while (y_eps >= 0) ++ { ++ src += y_inc; ++ y_eps -= dy2; ++ } ++ } ++ ++ for (yy = y1; yy < h_dst; yy++) ++ { ++ uint8_t *dst0 = dst; ++ ++ for (xx = 0; xx < w_dst; xx++) ++ { ++ *dst0 = init; ++ dst0 += x_inc; ++ } ++ ++ dst += y_inc; ++ } ++} ++ ++static void vdr_video_scale_YUY2(vdr_video_post_plugin_t *this, vo_frame_t *src, vo_frame_t *dst) ++{ ++ int w = dst->width - dst->crop_left - dst->crop_right; ++ int h = dst->height - dst->crop_top - dst->crop_bottom; ++ int offset; ++ ++ if (w < 0) ++ w = 0; ++ ++ if (h < 0) ++ h = 0; ++ ++ offset = dst->pitches[ 0 ] * dst->crop_top + 2 * dst->crop_left; ++ vdr_video_scale(&src->base[ 0 ][ 0 ] + offset, &dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 2, w , h, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x00); ++ offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2); ++ vdr_video_scale(&src->base[ 0 ][ 1 ] + offset, &dst->base[ 0 ][ 1 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80); ++ offset = dst->pitches[ 0 ] * dst->crop_top + 4 * ((dst->crop_left + 1) / 2); ++ vdr_video_scale(&src->base[ 0 ][ 3 ] + offset, &dst->base[ 0 ][ 3 ] + offset, dst->pitches[ 0 ], 4, (w + 1) / 2, h, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80); ++} ++ ++static void vdr_video_scale_YV12(vdr_video_post_plugin_t *this, vo_frame_t *src, vo_frame_t *dst) ++{ ++ int w = dst->width - dst->crop_left - dst->crop_right; ++ int h = dst->height - dst->crop_top - dst->crop_bottom; ++ int offset; ++ ++ if (w < 0) ++ w = 0; ++ ++ if (h < 0) ++ h = 0; ++ ++ offset = dst->pitches[ 0 ] * dst->crop_top + 1 * dst->crop_left; ++ vdr_video_scale(&src->base[ 0 ][ 0 ] + offset, &dst->base[ 0 ][ 0 ] + offset, dst->pitches[ 0 ], 1, w , h , this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x00); ++ offset = dst->pitches[ 1 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2); ++ vdr_video_scale(&src->base[ 1 ][ 0 ] + offset, &dst->base[ 1 ][ 0 ] + offset, dst->pitches[ 1 ], 1, (w + 1) / 2, (h + 1) / 2, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80); ++ offset = dst->pitches[ 2 ] * ((dst->crop_top + 1) / 2) + 1 * ((dst->crop_left + 1) / 2); ++ vdr_video_scale(&src->base[ 2 ][ 0 ] + offset, &dst->base[ 2 ][ 0 ] + offset, dst->pitches[ 2 ], 1, (w + 1) / 2, (h + 1) / 2, this->x, this->y, this->w, this->h, this->w_ref, this->h_ref, 0x80); ++} ++ ++ ++static int vdr_video_draw(vo_frame_t *frame, xine_stream_t *stream) ++{ ++ post_video_port_t *port = (post_video_port_t *)frame->port; ++ vdr_video_post_plugin_t *this = (vdr_video_post_plugin_t *)port->post; ++ vo_frame_t *vdr_frame; ++ xine_event_t *event; ++ int skip; ++ ++ if (this->vdr_stream ++ && !_x_continue_stream_processing(this->vdr_stream)) ++ { ++ this->vdr_stream = 0; ++ ++ xine_event_dispose_queue(this->event_queue); ++ this->event_queue = 0; ++ ++ this->old_frame_left = 0; ++ this->old_frame_top = 0; ++ this->old_frame_width = 0; ++ this->old_frame_height = 0; ++ this->old_frame_ratio = 0; ++ } ++ ++ if (!this->vdr_stream ++ && vdr_is_vdr_stream(stream)) ++ { ++ this->event_queue = xine_event_new_queue(stream); ++ if (this->event_queue) ++ { ++ this->vdr_stream = stream; ++ ++ { ++ xine_event_t event; ++ ++ event.type = XINE_EVENT_VDR_PLUGINSTARTED; ++ event.data = 0; ++ event.data_length = 0; /* vdr_video */ ++ ++ xine_event_send(this->vdr_stream, &event); ++ } ++ } ++ } ++ ++ if (this->event_queue) ++ { ++ while ((event = xine_event_get(this->event_queue))) ++ { ++ if (event->type == XINE_EVENT_VDR_SETVIDEOWINDOW) ++ { ++ vdr_set_video_window_data_t *data = (vdr_set_video_window_data_t *)event->data; ++ ++ vdr_video_set_video_window(this, data->x, data->y, data->w, data->h, data->w_ref, data->h_ref); ++ } ++ else if (event->type == XINE_EVENT_VDR_TRICKSPEEDMODE) ++ { ++/* ++ fprintf(stderr, "###############################: %p, %d\n", event->data, event->data_length); ++ this->trick_speed_mode = (0 != event->data_length); ++*/ ++ } ++ ++ xine_event_free(event); ++ } ++ } ++ ++ { ++ int32_t frame_left = frame->crop_left; ++ int32_t frame_width = frame->width - frame->crop_left - frame->crop_right; ++ int32_t frame_top = frame->crop_top; ++ int32_t frame_height = frame->height - frame->crop_top - frame->crop_bottom; ++ double frame_ratio = frame->ratio; ++ ++ if (frame_left < 0) ++ frame_left = 0; ++ if (frame_width > frame->width) ++ frame_width = frame->width; ++ if (frame_top < 0) ++ frame_top = 0; ++ if (frame_height > frame->height) ++ frame_height = frame->height; ++ ++ if (this->vdr_stream ++ && frame_width != 0 ++ && frame_height != 0 ++ && (this->old_frame_left != frame_left ++ || this->old_frame_top != frame_top ++ || this->old_frame_width != frame_width ++ || this->old_frame_height != frame_height ++ || this->old_frame_ratio != frame_ratio)) ++ { ++ xine_event_t event; ++ vdr_frame_size_changed_data_t event_data; ++ ++ event_data.x = frame_left; ++ event_data.y = frame_top; ++ event_data.w = frame_width; ++ event_data.h = frame_height; ++ event_data.r = frame_ratio; ++ ++ xprintf(this->vdr_stream->xine, XINE_VERBOSITY_LOG, ++ _(LOG_MODULE ": osd: (%d, %d)-(%d, %d)@%lg\n"), frame_left, frame_top, frame_width, frame_height, frame_ratio); ++ ++ event.type = XINE_EVENT_VDR_FRAMESIZECHANGED; ++ event.data = &event_data; ++ event.data_length = sizeof (event_data); ++ ++ xine_event_send(this->vdr_stream, &event); ++ ++ this->old_frame_left = frame_left; ++ this->old_frame_top = frame_top; ++ this->old_frame_width = frame_width; ++ this->old_frame_height = frame_height; ++ this->old_frame_ratio = frame_ratio; ++ } ++ } ++/* ++ fprintf(stderr, "~~~~~~~~~~~~ trickspeedmode: %d\n", this->trick_speed_mode); ++ ++ if (this->vdr_stream ++ && this->trick_speed_mode) ++ { ++ frame->pts = 0; ++ frame->next->pts = 0; ++ } ++*/ ++#if defined(LOG) && defined(LOG_VERBOSE) ++ { ++ int a = 0, b = 0, c = 0, d = 0; ++ if (stream) ++ _x_query_buffer_usage(stream, &a, &b, &c, &d); ++ lprintf("buffer usage: %3d, %2d, %2d, %2d, %p\n", a, b, c, d, stream); ++ } ++#endif ++ ++ if (!this->enabled ++ || frame->bad_frame ++ || (frame->format != XINE_IMGFMT_YUY2 ++ && frame->format != XINE_IMGFMT_YV12) ++ || frame->proc_frame ++ || frame->proc_slice) ++ { ++ _x_post_frame_copy_down(frame, frame->next); ++ skip = frame->next->draw(frame->next, stream); ++ _x_post_frame_copy_up(frame, frame->next); ++ return skip; ++ } ++ ++ vdr_frame = port->original_port->get_frame(port->original_port, ++ frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS); ++ ++ _x_post_frame_copy_down(frame, vdr_frame); ++ ++ switch (vdr_frame->format) ++ { ++ case XINE_IMGFMT_YUY2: ++ vdr_video_scale_YUY2(this, frame, vdr_frame); ++ break; ++ ++ case XINE_IMGFMT_YV12: ++ vdr_video_scale_YV12(this, frame, vdr_frame); ++ break; ++ } ++ ++ skip = vdr_frame->draw(vdr_frame, stream); ++ _x_post_frame_copy_up(frame, vdr_frame); ++ vdr_frame->free(vdr_frame); ++ ++ return skip; ++} +--- /dev/null ++++ xine-lib-1.1.19/src/vdr/Makefile.in +@@ -0,0 +1,849 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# @configure_input@ ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++@SET_MAKE@ ++ ++ ++VPATH = @srcdir@ ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkglibexecdir = $(libexecdir)/@PACKAGE@ ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = @build@ ++host_triplet = @host@ ++DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ ++ $(srcdir)/Makefile.in $(top_srcdir)/misc/Makefile.common \ ++ $(xineinclude_HEADERS) ++subdir = src/vdr ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/_xine.m4 $(top_srcdir)/m4/aa.m4 \ ++ $(top_srcdir)/m4/arts.m4 $(top_srcdir)/m4/attributes.m4 \ ++ $(top_srcdir)/m4/directx.m4 $(top_srcdir)/m4/dl.m4 \ ++ $(top_srcdir)/m4/dvdnav.m4 $(top_srcdir)/m4/gas.m4 \ ++ $(top_srcdir)/m4/getopt_long.m4 $(top_srcdir)/m4/gettext.m4 \ ++ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ ++ $(top_srcdir)/m4/ioctl_request.m4 $(top_srcdir)/m4/irixal.m4 \ ++ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lib-ld.m4 \ ++ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ ++ $(top_srcdir)/m4/libFLAC.m4 $(top_srcdir)/m4/libfame.m4 \ ++ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ ++ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ ++ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/misc.m4 \ ++ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/opengl.m4 \ ++ $(top_srcdir)/m4/optimizations.m4 $(top_srcdir)/m4/pkg.m4 \ ++ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ ++ $(top_srcdir)/m4/pthreads.m4 $(top_srcdir)/m4/symbol.m4 \ ++ $(top_srcdir)/m4/xv.m4 $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/include/configure.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; ++am__vpath_adj = case $$p in \ ++ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ ++ *) f=$$p;; \ ++ esac; ++am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; ++am__install_max = 40 ++am__nobase_strip_setup = \ ++ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` ++am__nobase_strip = \ ++ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" ++am__nobase_list = $(am__nobase_strip_setup); \ ++ for p in $$list; do echo "$$p $$p"; done | \ ++ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ ++ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ ++ if (++n[$$2] == $(am__install_max)) \ ++ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ ++ END { for (dir in files) print dir, files[dir] }' ++am__base_list = \ ++ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ ++ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' ++am__installdirs = "$(DESTDIR)$(xineplugdir)" \ ++ "$(DESTDIR)$(xineincludedir)" ++LTLIBRARIES = $(xineplug_LTLIBRARIES) ++xineplug_vdr_la_DEPENDENCIES = $(XINE_LIB) ++am_xineplug_vdr_la_OBJECTS = combined_vdr.lo input_vdr.lo \ ++ post_vdr_video.lo post_vdr_audio.lo ++xineplug_vdr_la_OBJECTS = $(am_xineplug_vdr_la_OBJECTS) ++xineplug_vdr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ ++ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ ++ $(xineplug_vdr_la_LDFLAGS) $(LDFLAGS) -o $@ ++DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include ++depcomp = $(SHELL) $(top_srcdir)/depcomp ++am__depfiles_maybe = depfiles ++am__mv = mv -f ++COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ ++ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ ++ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++CCLD = $(CC) ++LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ ++ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ ++ $(LDFLAGS) -o $@ ++SOURCES = $(xineplug_vdr_la_SOURCES) ++DIST_SOURCES = $(xineplug_vdr_la_SOURCES) ++HEADERS = $(noinst_HEADERS) $(xineinclude_HEADERS) ++ETAGS = etags ++CTAGS = ctags ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++AAINFO = @AAINFO@ ++AALIB_CFLAGS = @AALIB_CFLAGS@ ++AALIB_CONFIG = @AALIB_CONFIG@ ++AALIB_LIBS = @AALIB_LIBS@ ++ACLOCAL = @ACLOCAL@ ++ACLOCAL_DIR = @ACLOCAL_DIR@ ++ALSA_CFLAGS = @ALSA_CFLAGS@ ++ALSA_LIBS = @ALSA_LIBS@ ++AMTAR = @AMTAR@ ++AR = @AR@ ++ARTS_CFLAGS = @ARTS_CFLAGS@ ++ARTS_CONFIG = @ARTS_CONFIG@ ++ARTS_LIBS = @ARTS_LIBS@ ++AS = @AS@ ++ASFLAGS = @ASFLAGS@ ++AUTOCONF = @AUTOCONF@ ++AUTOHEADER = @AUTOHEADER@ ++AUTOMAKE = @AUTOMAKE@ ++AWK = @AWK@ ++CACA_CFLAGS = @CACA_CFLAGS@ ++CACA_LIBS = @CACA_LIBS@ ++CC = @CC@ ++CCAS = @CCAS@ ++CCASDEPMODE = @CCASDEPMODE@ ++CCASFLAGS = @CCASFLAGS@ ++CCDEPMODE = @CCDEPMODE@ ++CFLAGS = @CFLAGS@ ++CPP = @CPP@ ++CPPFLAGS = @CPPFLAGS@ ++CYGPATH_W = @CYGPATH_W@ ++DEBUG_CFLAGS = @DEBUG_CFLAGS@ ++DEFS = @DEFS@ ++DEPCOMP = @DEPCOMP@ ++DEPDIR = @DEPDIR@ ++DEPMOD = @DEPMOD@ ++DIRECTFB_CFLAGS = @DIRECTFB_CFLAGS@ ++DIRECTFB_LIBS = @DIRECTFB_LIBS@ ++DIRECTX_AUDIO_LIBS = @DIRECTX_AUDIO_LIBS@ ++DIRECTX_CPPFLAGS = @DIRECTX_CPPFLAGS@ ++DIRECTX_VIDEO_LIBS = @DIRECTX_VIDEO_LIBS@ ++DLLTOOL = @DLLTOOL@ ++DSYMUTIL = @DSYMUTIL@ ++DUMPBIN = @DUMPBIN@ ++DVDNAV_CFLAGS = @DVDNAV_CFLAGS@ ++DVDNAV_CONFIG = @DVDNAV_CONFIG@ ++DVDNAV_LIBS = @DVDNAV_LIBS@ ++DYNAMIC_LD_LIBS = @DYNAMIC_LD_LIBS@ ++ECHO_C = @ECHO_C@ ++ECHO_N = @ECHO_N@ ++ECHO_T = @ECHO_T@ ++EGREP = @EGREP@ ++ESD_CFLAGS = @ESD_CFLAGS@ ++ESD_LIBS = @ESD_LIBS@ ++EXEEXT = @EXEEXT@ ++EXTRA_X_CFLAGS = @EXTRA_X_CFLAGS@ ++EXTRA_X_LIBS = @EXTRA_X_LIBS@ ++FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ ++FFMPEG_LIBS = @FFMPEG_LIBS@ ++FFMPEG_POSTPROC_CFLAGS = @FFMPEG_POSTPROC_CFLAGS@ ++FFMPEG_POSTPROC_LIBS = @FFMPEG_POSTPROC_LIBS@ ++FFMPEG_UTIL_CFLAGS = @FFMPEG_UTIL_CFLAGS@ ++FFMPEG_UTIL_LIBS = @FFMPEG_UTIL_LIBS@ ++FGREP = @FGREP@ ++FIG2DEV = @FIG2DEV@ ++FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ ++FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ ++FT2_CFLAGS = @FT2_CFLAGS@ ++FT2_LIBS = @FT2_LIBS@ ++FUSIONSOUND_CFLAGS = @FUSIONSOUND_CFLAGS@ ++FUSIONSOUND_LIBS = @FUSIONSOUND_LIBS@ ++GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ ++GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ ++GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ ++GLU_LIBS = @GLU_LIBS@ ++GMSGFMT = @GMSGFMT@ ++GMSGFMT_015 = @GMSGFMT_015@ ++GNOME_VFS_CFLAGS = @GNOME_VFS_CFLAGS@ ++GNOME_VFS_LIBS = @GNOME_VFS_LIBS@ ++GOOM_LIBS = @GOOM_LIBS@ ++GRAPHICSMAGICKWAND_CFLAGS = @GRAPHICSMAGICKWAND_CFLAGS@ ++GRAPHICSMAGICKWAND_LIBS = @GRAPHICSMAGICKWAND_LIBS@ ++GRAPHICSMAGICK_CFLAGS = @GRAPHICSMAGICK_CFLAGS@ ++GRAPHICSMAGICK_LIBS = @GRAPHICSMAGICK_LIBS@ ++GREP = @GREP@ ++HAVE_BSDI_CDROM = @HAVE_BSDI_CDROM@ ++HAVE_DARWIN_CDROM = @HAVE_DARWIN_CDROM@ ++HAVE_FREEBSD_CDROM = @HAVE_FREEBSD_CDROM@ ++HAVE_LINUX_CDROM = @HAVE_LINUX_CDROM@ ++HAVE_SOLARIS_CDROM = @HAVE_SOLARIS_CDROM@ ++HAVE_WIN32_CDROM = @HAVE_WIN32_CDROM@ ++IMPURE_TEXT_LDFLAGS = @IMPURE_TEXT_LDFLAGS@ ++INCLUDES = @INCLUDES@ ++INSTALL = @INSTALL@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ ++INTLLIBS = @INTLLIBS@ ++INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ ++IRIXAL_CFLAGS = @IRIXAL_CFLAGS@ ++IRIXAL_LIBS = @IRIXAL_LIBS@ ++IRIXAL_STATIC_LIB = @IRIXAL_STATIC_LIB@ ++JACK_CFLAGS = @JACK_CFLAGS@ ++JACK_LIBS = @JACK_LIBS@ ++KSTAT_LIBS = @KSTAT_LIBS@ ++LD = @LD@ ++LDFLAGS = @LDFLAGS@ ++LDFLAGS_NOUNDEFINED = @LDFLAGS_NOUNDEFINED@ ++LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@ ++LIBCDIO_LIBS = @LIBCDIO_LIBS@ ++LIBDTS_CFLAGS = @LIBDTS_CFLAGS@ ++LIBDTS_LIBS = @LIBDTS_LIBS@ ++LIBFAME_CFLAGS = @LIBFAME_CFLAGS@ ++LIBFAME_CONFIG = @LIBFAME_CONFIG@ ++LIBFAME_LIBS = @LIBFAME_LIBS@ ++LIBFFMPEG_CPPFLAGS = @LIBFFMPEG_CPPFLAGS@ ++LIBFLAC_CFLAGS = @LIBFLAC_CFLAGS@ ++LIBFLAC_LIBS = @LIBFLAC_LIBS@ ++LIBICONV = @LIBICONV@ ++LIBINTL = @LIBINTL@ ++LIBISO9660_LIBS = @LIBISO9660_LIBS@ ++LIBMAD_CFLAGS = @LIBMAD_CFLAGS@ ++LIBMAD_LIBS = @LIBMAD_LIBS@ ++LIBMODPLUG_CFLAGS = @LIBMODPLUG_CFLAGS@ ++LIBMODPLUG_LIBS = @LIBMODPLUG_LIBS@ ++LIBMPEG2_CFLAGS = @LIBMPEG2_CFLAGS@ ++LIBNAME = @LIBNAME@ ++LIBOBJS = @LIBOBJS@ ++LIBS = @LIBS@ ++LIBSMBCLIENT_LIBS = @LIBSMBCLIENT_LIBS@ ++LIBSTK_CFLAGS = @LIBSTK_CFLAGS@ ++LIBSTK_LIBS = @LIBSTK_LIBS@ ++LIBTOOL = @LIBTOOL@ ++LIBTOOL_DEPS = @LIBTOOL_DEPS@ ++LIBTOOL_DESTDIR_DEFAULT = @LIBTOOL_DESTDIR_DEFAULT@ ++LIBVCDINFO_CFLAGS = @LIBVCDINFO_CFLAGS@ ++LIBVCDINFO_LIBS = @LIBVCDINFO_LIBS@ ++LIBVCD_CFLAGS = @LIBVCD_CFLAGS@ ++LIBVCD_LIBS = @LIBVCD_LIBS@ ++LIBVCD_SYSDEP = @LIBVCD_SYSDEP@ ++LINUX_CDROM_TIMEOUT = @LINUX_CDROM_TIMEOUT@ ++LINUX_INCLUDE = @LINUX_INCLUDE@ ++LIPO = @LIPO@ ++LN_S = @LN_S@ ++LTLIBICONV = @LTLIBICONV@ ++LTLIBINTL = @LTLIBINTL@ ++LTLIBOBJS = @LTLIBOBJS@ ++MAGICKWAND_CFLAGS = @MAGICKWAND_CFLAGS@ ++MAGICKWAND_LIBS = @MAGICKWAND_LIBS@ ++MAKEINFO = @MAKEINFO@ ++MKDIR_P = @MKDIR_P@ ++MKINSTALLDIRS = @MKINSTALLDIRS@ ++MKNOD = @MKNOD@ ++MLIB_CFLAGS = @MLIB_CFLAGS@ ++MLIB_LIBS = @MLIB_LIBS@ ++MNG_LIBS = @MNG_LIBS@ ++MSGFMT = @MSGFMT@ ++MSGFMT_015 = @MSGFMT_015@ ++MSGMERGE = @MSGMERGE@ ++NET_LIBS = @NET_LIBS@ ++NM = @NM@ ++NMEDIT = @NMEDIT@ ++OBJC = @OBJC@ ++OBJCDEPMODE = @OBJCDEPMODE@ ++OBJCFLAGS = @OBJCFLAGS@ ++OBJDUMP = @OBJDUMP@ ++OBJEXT = @OBJEXT@ ++OPENGL_CFLAGS = @OPENGL_CFLAGS@ ++OPENGL_LIBS = @OPENGL_LIBS@ ++OTOOL = @OTOOL@ ++OTOOL64 = @OTOOL64@ ++PACKAGE = @PACKAGE@ ++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_STRING = @PACKAGE_STRING@ ++PACKAGE_TARNAME = @PACKAGE_TARNAME@ ++PACKAGE_URL = @PACKAGE_URL@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++PASS1_CFLAGS = @PASS1_CFLAGS@ ++PASS2_CFLAGS = @PASS2_CFLAGS@ ++PATH_SEPARATOR = @PATH_SEPARATOR@ ++PERL = @PERL@ ++PKG_CONFIG = @PKG_CONFIG@ ++POSUB = @POSUB@ ++PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ ++PTHREAD_LIBS = @PTHREAD_LIBS@ ++PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ ++PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ ++RANLIB = @RANLIB@ ++RT_LIBS = @RT_LIBS@ ++SDL_CFLAGS = @SDL_CFLAGS@ ++SDL_LIBS = @SDL_LIBS@ ++SED = @SED@ ++SET_MAKE = @SET_MAKE@ ++SGMLTOOLS = @SGMLTOOLS@ ++SHELL = @SHELL@ ++SNDIO_CFLAGS = @SNDIO_CFLAGS@ ++SNDIO_LIBS = @SNDIO_LIBS@ ++SPEC_VERSION = @SPEC_VERSION@ ++SPEEX_CFLAGS = @SPEEX_CFLAGS@ ++SPEEX_LIBS = @SPEEX_LIBS@ ++STATIC = @STATIC@ ++STRINGS = @STRINGS@ ++STRIP = @STRIP@ ++SUNDGA_CFLAGS = @SUNDGA_CFLAGS@ ++SUNDGA_LIBS = @SUNDGA_LIBS@ ++TAR_NAME = @TAR_NAME@ ++THEORA_CFLAGS = @THEORA_CFLAGS@ ++THEORA_LIBS = @THEORA_LIBS@ ++USE_NLS = @USE_NLS@ ++V4L2_CFLAGS = @V4L2_CFLAGS@ ++V4L2_LIBS = @V4L2_LIBS@ ++VERSION = @VERSION@ ++VISIBILITY_FLAG = @VISIBILITY_FLAG@ ++VORBIS_CFLAGS = @VORBIS_CFLAGS@ ++VORBIS_LIBS = @VORBIS_LIBS@ ++W32_NO_OPTIMIZE = @W32_NO_OPTIMIZE@ ++WAND_CFLAGS = @WAND_CFLAGS@ ++WAND_LIBS = @WAND_LIBS@ ++WAVPACK_CFLAGS = @WAVPACK_CFLAGS@ ++WAVPACK_LIBS = @WAVPACK_LIBS@ ++WIN32_CPPFLAGS = @WIN32_CPPFLAGS@ ++XCBSHM_CFLAGS = @XCBSHM_CFLAGS@ ++XCBSHM_LIBS = @XCBSHM_LIBS@ ++XCBXV_CFLAGS = @XCBXV_CFLAGS@ ++XCBXV_LIBS = @XCBXV_LIBS@ ++XCB_CFLAGS = @XCB_CFLAGS@ ++XCB_LIBS = @XCB_LIBS@ ++XGETTEXT = @XGETTEXT@ ++XGETTEXT_015 = @XGETTEXT_015@ ++XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ ++XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ ++XINERAMA_LIBS = @XINERAMA_LIBS@ ++XINE_ACFLAGS = @XINE_ACFLAGS@ ++XINE_BIN_AGE = @XINE_BIN_AGE@ ++XINE_BUILD_CC = @XINE_BUILD_CC@ ++XINE_BUILD_DATE = @XINE_BUILD_DATE@ ++XINE_BUILD_OS = @XINE_BUILD_OS@ ++XINE_DATADIR = @XINE_DATADIR@ ++XINE_FONTDIR = @XINE_FONTDIR@ ++XINE_IFACE_AGE = @XINE_IFACE_AGE@ ++XINE_LOCALEDIR = @XINE_LOCALEDIR@ ++XINE_LT_AGE = @XINE_LT_AGE@ ++XINE_LT_CURRENT = @XINE_LT_CURRENT@ ++XINE_LT_REVISION = @XINE_LT_REVISION@ ++XINE_MAJOR = @XINE_MAJOR@ ++XINE_MINOR = @XINE_MINOR@ ++XINE_PATCH = @XINE_PATCH@ ++XINE_PKGCONFIG_DIR = @XINE_PKGCONFIG_DIR@ ++XINE_PLUGINDIR = @XINE_PLUGINDIR@ ++XINE_SCRIPTPATH = @XINE_SCRIPTPATH@ ++XINE_SERIES = @XINE_SERIES@ ++XINE_SUB = @XINE_SUB@ ++XMKMF = @XMKMF@ ++XVMC_LIBS = @XVMC_LIBS@ ++XV_CFLAGS = @XV_CFLAGS@ ++XV_LIBS = @XV_LIBS@ ++XXMC_LIBS = @XXMC_LIBS@ ++X_CFLAGS = @X_CFLAGS@ ++X_EXTRA_LIBS = @X_EXTRA_LIBS@ ++X_LIBS = @X_LIBS@ ++X_PRE_LIBS = @X_PRE_LIBS@ ++ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ++ZLIB_LIBS = @ZLIB_LIBS@ ++abs_builddir = @abs_builddir@ ++abs_srcdir = @abs_srcdir@ ++abs_top_builddir = @abs_top_builddir@ ++abs_top_srcdir = @abs_top_srcdir@ ++ac_ct_CC = @ac_ct_CC@ ++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ++ac_ct_OBJC = @ac_ct_OBJC@ ++am__include = @am__include@ ++am__leading_dot = @am__leading_dot@ ++am__quote = @am__quote@ ++am__tar = @am__tar@ ++am__untar = @am__untar@ ++bindir = @bindir@ ++build = @build@ ++build_alias = @build_alias@ ++build_cpu = @build_cpu@ ++build_os = @build_os@ ++build_vendor = @build_vendor@ ++builddir = @builddir@ ++datadir = @datadir@ ++datarootdir = @datarootdir@ ++docdir = @docdir@ ++dvidir = @dvidir@ ++exec_prefix = @exec_prefix@ ++host = @host@ ++host_alias = @host_alias@ ++host_cpu = @host_cpu@ ++host_os = @host_os@ ++host_vendor = @host_vendor@ ++htmldir = @htmldir@ ++includedir = @includedir@ ++infodir = @infodir@ ++install_sh = @install_sh@ ++libdir = @libdir@ ++libexecdir = @libexecdir@ ++localedir = @localedir@ ++localstatedir = @localstatedir@ ++lt_ECHO = @lt_ECHO@ ++mandir = @mandir@ ++mkdir_p = @mkdir_p@ ++oldincludedir = @oldincludedir@ ++pdfdir = @pdfdir@ ++pkgconfigdir = @pkgconfigdir@ ++prefix = @prefix@ ++program_transform_name = @program_transform_name@ ++psdir = @psdir@ ++sbindir = @sbindir@ ++sharedstatedir = @sharedstatedir@ ++srcdir = @srcdir@ ++sysconfdir = @sysconfdir@ ++target_alias = @target_alias@ ++top_build_prefix = @top_build_prefix@ ++top_builddir = @top_builddir@ ++top_srcdir = @top_srcdir@ ++w32_path = @w32_path@ ++xinedatadir = @xinedatadir@ ++xinelibdir = @xinelibdir@ ++XINE_LIB = $(top_builddir)/src/xine-engine/libxine.la ++xineincludedir = $(includedir)/xine ++xineplugdir = $(XINE_PLUGINDIR) ++xineplug_ldflags = $(LDFLAGS_NOUNDEFINED) -avoid-version -module ++xinepostdir = $(XINE_PLUGINDIR)/post ++vidixdir = $(XINE_PLUGINDIR)/vidix ++AM_CFLAGS = -D_LARGEFILE64_SOURCE ++xineplug_LTLIBRARIES = \ ++ xineplug_vdr.la ++ ++xineplug_vdr_la_SOURCES = combined_vdr.c input_vdr.c post_vdr_video.c post_vdr_audio.c ++xineplug_vdr_la_LIBADD = $(XINE_LIB) ++xineplug_vdr_la_LDFLAGS = -avoid-version -module @IMPURE_TEXT_LDFLAGS@ ++xineinclude_HEADERS = vdr.h ++noinst_HEADERS = combined_vdr.h ++all: all-am ++ ++.SUFFIXES: ++.SUFFIXES: .c .lo .o .obj ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/misc/Makefile.common $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/vdr/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --gnu src/vdr/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++install-xineplugLTLIBRARIES: $(xineplug_LTLIBRARIES) ++ @$(NORMAL_INSTALL) ++ test -z "$(xineplugdir)" || $(MKDIR_P) "$(DESTDIR)$(xineplugdir)" ++ @list='$(xineplug_LTLIBRARIES)'; test -n "$(xineplugdir)" || list=; \ ++ list2=; for p in $$list; do \ ++ if test -f $$p; then \ ++ list2="$$list2 $$p"; \ ++ else :; fi; \ ++ done; \ ++ test -z "$$list2" || { \ ++ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(xineplugdir)'"; \ ++ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(xineplugdir)"; \ ++ } ++ ++uninstall-xineplugLTLIBRARIES: ++ @$(NORMAL_UNINSTALL) ++ @list='$(xineplug_LTLIBRARIES)'; test -n "$(xineplugdir)" || list=; \ ++ for p in $$list; do \ ++ $(am__strip_dir) \ ++ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(xineplugdir)/$$f'"; \ ++ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(xineplugdir)/$$f"; \ ++ done ++ ++clean-xineplugLTLIBRARIES: ++ -test -z "$(xineplug_LTLIBRARIES)" || rm -f $(xineplug_LTLIBRARIES) ++ @list='$(xineplug_LTLIBRARIES)'; for p in $$list; do \ ++ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ ++ test "$$dir" != "$$p" || dir=.; \ ++ echo "rm -f \"$${dir}/so_locations\""; \ ++ rm -f "$${dir}/so_locations"; \ ++ done ++xineplug_vdr.la: $(xineplug_vdr_la_OBJECTS) $(xineplug_vdr_la_DEPENDENCIES) ++ $(xineplug_vdr_la_LINK) -rpath $(xineplugdir) $(xineplug_vdr_la_OBJECTS) $(xineplug_vdr_la_LIBADD) $(LIBS) ++ ++mostlyclean-compile: ++ -rm -f *.$(OBJEXT) ++ ++distclean-compile: ++ -rm -f *.tab.c ++ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/combined_vdr.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input_vdr.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/post_vdr_audio.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/post_vdr_video.Plo@am__quote@ ++ ++.c.o: ++@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(COMPILE) -c $< ++ ++.c.obj: ++@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` ++ ++.c.lo: ++@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++install-xineincludeHEADERS: $(xineinclude_HEADERS) ++ @$(NORMAL_INSTALL) ++ test -z "$(xineincludedir)" || $(MKDIR_P) "$(DESTDIR)$(xineincludedir)" ++ @list='$(xineinclude_HEADERS)'; test -n "$(xineincludedir)" || list=; \ ++ for p in $$list; do \ ++ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ ++ echo "$$d$$p"; \ ++ done | $(am__base_list) | \ ++ while read files; do \ ++ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(xineincludedir)'"; \ ++ $(INSTALL_HEADER) $$files "$(DESTDIR)$(xineincludedir)" || exit $$?; \ ++ done ++ ++uninstall-xineincludeHEADERS: ++ @$(NORMAL_UNINSTALL) ++ @list='$(xineinclude_HEADERS)'; test -n "$(xineincludedir)" || list=; \ ++ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ ++ test -n "$$files" || exit 0; \ ++ echo " ( cd '$(DESTDIR)$(xineincludedir)' && rm -f" $$files ")"; \ ++ cd "$(DESTDIR)$(xineincludedir)" && rm -f $$files ++ ++ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) ++ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | \ ++ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in files) print i; }; }'`; \ ++ mkid -fID $$unique ++tags: TAGS ++ ++TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ ++ $(TAGS_FILES) $(LISP) ++ set x; \ ++ here=`pwd`; \ ++ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | \ ++ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in files) print i; }; }'`; \ ++ shift; \ ++ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ ++ test -n "$$unique" || unique=$$empty_fix; \ ++ if test $$# -gt 0; then \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ "$$@" $$unique; \ ++ else \ ++ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ ++ $$unique; \ ++ fi; \ ++ fi ++ctags: CTAGS ++CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ ++ $(TAGS_FILES) $(LISP) ++ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ ++ unique=`for i in $$list; do \ ++ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ ++ done | \ ++ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ ++ END { if (nonempty) { for (i in files) print i; }; }'`; \ ++ test -z "$(CTAGS_ARGS)$$unique" \ ++ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ ++ $$unique ++ ++GTAGS: ++ here=`$(am__cd) $(top_builddir) && pwd` \ ++ && $(am__cd) $(top_srcdir) \ ++ && gtags -i $(GTAGS_ARGS) "$$here" ++ ++distclean-tags: ++ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile $(LTLIBRARIES) $(HEADERS) ++installdirs: ++ for dir in "$(DESTDIR)$(xineplugdir)" "$(DESTDIR)$(xineincludedir)"; do \ ++ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ ++ done ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-xineplugLTLIBRARIES \ ++ mostlyclean-am ++ ++distclean: distclean-am ++ -rm -rf ./$(DEPDIR) ++ -rm -f Makefile ++distclean-am: clean-am distclean-compile distclean-generic \ ++ distclean-tags ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: install-xineincludeHEADERS \ ++ install-xineplugLTLIBRARIES ++ @$(NORMAL_INSTALL) ++ $(MAKE) $(AM_MAKEFLAGS) install-data-hook ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -rf ./$(DEPDIR) ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-compile mostlyclean-generic \ ++ mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: uninstall-xineincludeHEADERS \ ++ uninstall-xineplugLTLIBRARIES ++ @$(NORMAL_INSTALL) ++ $(MAKE) $(AM_MAKEFLAGS) uninstall-hook ++.MAKE: install-am install-data-am install-strip uninstall-am ++ ++.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ ++ clean-libtool clean-xineplugLTLIBRARIES ctags distclean \ ++ distclean-compile distclean-generic distclean-libtool \ ++ distclean-tags distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am \ ++ install-data-hook install-dvi install-dvi-am install-exec \ ++ install-exec-am install-html install-html-am install-info \ ++ install-info-am install-man install-pdf install-pdf-am \ ++ install-ps install-ps-am install-strip \ ++ install-xineincludeHEADERS install-xineplugLTLIBRARIES \ ++ installcheck installcheck-am installdirs maintainer-clean \ ++ maintainer-clean-generic mostlyclean mostlyclean-compile \ ++ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ ++ tags uninstall uninstall-am uninstall-hook \ ++ uninstall-xineincludeHEADERS uninstall-xineplugLTLIBRARIES ++ ++ ++$(XINE_LIB): ++ @cd $(top_builddir)/src/xine-engine && $(MAKE) ++ ++install-data-hook: ++ @if test $$MAKELEVEL -le 4 ; then \ ++ if test -x "$(top_srcdir)/post-install.sh" ; then \ ++ $(top_srcdir)/post-install.sh ; \ ++ fi; \ ++ fi; \ ++ if test -x /usr/bin/chcon -a "`id -u`" -eq 0; then \ ++ list='$(xineplug_LTLIBRARIES)'; \ ++ for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xineplugdir)/$$p"; \ ++ chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xineplugdir)/$$p || :; \ ++ done; \ ++ list='$(xinepost_LTLIBRARIES)'; \ ++ for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xinepostdir)/$$p"; \ ++ chcon system_u:object_r:texrel_shlib_t $(DESTDIR)$(xinepostdir)/$$p || :; \ ++ done; \ ++ fi ++ ++pass1: ++ @$(MAKE) MULTIPASS_CFLAGS="$(PASS1_CFLAGS)" ++ ++pass2: ++ @$(MAKE) MULTIPASS_CFLAGS="$(PASS2_CFLAGS)" ++ ++debug: ++ @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" ++ ++install-debug: debug ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ @list='$(SUBDIRS)'; for subdir in $$list; do \ ++ (cd $$subdir && $(MAKE) $@) || exit; \ ++ done; ++ $(MAKE) $(AM_MAKEFLAGS) install-data-hook ++ ++uninstall-hook: ++ @list='$(xineplug_LTLIBRARIES)'; for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " rm -f $(DESTDIR)$(xineplugdir)/$$p"; \ ++ rm -f $(DESTDIR)$(xineplugdir)/$$p; \ ++ done; ++ @list='$(xinepost_LTLIBRARIES)'; for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " rm -f $(DESTDIR)$(xinepostdir)/$$p"; \ ++ rm -f $(DESTDIR)$(xinepostdir)/$$p; \ ++ done; ++ @list='$(vidix_LTLIBRARIES)'; for p in $$list; do \ ++ p="`echo $$p | sed -e 's/\.la$$/\.so/g;s|^.*/||'`"; \ ++ echo " rm -f $(DESTDIR)$(vidixdir)/$$p"; \ ++ rm -f $(DESTDIR)$(vidixdir)/$$p; \ ++ done; ++ ++mostlyclean-generic: ++ -rm -f *~ \#* .*~ .\#* ++ ++maintainer-clean-generic: ++ -@echo "This command is intended for maintainers to use;" ++ -@echo "it deletes files that may require special tools to rebuild." ++ -rm -f Makefile.in ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: +--- xine-lib-1.1.19.orig/src/input/input_vcd.c ++++ xine-lib-1.1.19/src/input/input_vcd.c +@@ -93,7 +93,7 @@ typedef struct { + #if defined (__linux__) || defined(__sun) + struct cdrom_tochdr tochdr; + struct cdrom_tocentry tocent[100]; +-#elif (defined(BSD) && BSD >= 199306) ++#elif defined (__FreeBSD_kernel__) || (defined(BSD) && BSD >= 199306) + struct ioc_toc_header tochdr; + struct cd_toc_entry *tocent; + off_t cur_sec; +@@ -118,7 +118,7 @@ typedef struct { + + int cur_track; + +-#if defined (__linux__) || defined(__sun) || (defined(BSD) && BSD >= 199306) ++#if defined (__linux__) || defined(__sun) || defined (__FreeBSD_kernel__) || (defined(BSD) && BSD >= 199306) + uint8_t cur_min, cur_sec, cur_frame; + #endif + +@@ -178,7 +178,7 @@ static int input_vcd_read_toc (vcd_input + + return 0; + } +-#elif (defined(BSD) && BSD >= 199306) ++#elif defined (__FreeBSD_kernel__) || (defined(BSD) && BSD >= 199306) + static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { + + struct ioc_read_toc_entry te; +@@ -394,7 +394,7 @@ static off_t vcd_plugin_read (input_plug + memcpy (buf, data.data, VCDSECTORSIZE); /* FIXME */ + return VCDSECTORSIZE; + } +-#elif (defined(BSD) && BSD >= 199306) ++#elif defined (__FreeBSD_kernel__) || (defined(BSD) && BSD >= 199306) + static off_t vcd_plugin_read (input_plugin_t *this_gen, + char *buf, off_t nlen) { + vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; +@@ -532,7 +532,7 @@ static buf_element_t *vcd_plugin_read_bl + memcpy (buf->mem, data.data, VCDSECTORSIZE); /* FIXME */ + return buf; + } +-#elif (defined(BSD) && BSD >= 199306) ++#elif defined (__FreeBSD_kernel__) || (defined(BSD) && BSD >= 199306) + static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, + fifo_buffer_t *fifo, off_t nlen) { + +@@ -691,7 +691,7 @@ static off_t vcd_plugin_seek (input_plug + + return offset ; /* FIXME */ + } +-#elif (defined(BSD) && BSD >= 199306) ++#elif defined (__FreeBSD_kernel__) || (defined(BSD) && BSD >= 199306) + static off_t vcd_plugin_seek (input_plugin_t *this_gen, + off_t offset, int origin) { + +@@ -765,7 +765,7 @@ static off_t vcd_plugin_get_length (inpu + + return (off_t) 0; + } +-#elif (defined(BSD) && BSD >= 199306) ++#elif defined (__FreeBSD_kernel__) || (defined(BSD) && BSD >= 199306) + static off_t vcd_plugin_get_length (input_plugin_t *this_gen) { + vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; + off_t len ; +--- xine-lib-1.1.19.orig/src/xine-utils/utils.c ++++ xine-lib-1.1.19/src/xine-utils/utils.c +@@ -460,21 +460,13 @@ void xine_usec_sleep(unsigned usec) { + /* select does not work on win32 */ + Sleep(usec / 1000); + #else +-# if 0 + # if HAVE_NANOSLEEP +- /* nanosleep is prefered on solaris, because it's mt-safe */ + struct timespec ts, remaining; + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + while (nanosleep (&ts, &remaining) == -1 && errno == EINTR) + ts = remaining; + # else +- usleep(usec); +-# endif +-# else +- if (usec < 10000) { +- usec = 10000; +- } + struct timeval tm; + tm.tv_sec = usec / 1000000; + tm.tv_usec = usec % 1000000; +--- xine-lib-1.1.19.orig/include/xine.h.in ++++ xine-lib-1.1.19/include/xine.h.in +@@ -376,12 +376,13 @@ int xine_get_param (xine_stream_t *stre + #define XINE_PARAM_VO_TVMODE 0x0100000a /* ??? */ + #define XINE_PARAM_VO_WINDOW_WIDTH 0x0100000f /* readonly */ + #define XINE_PARAM_VO_WINDOW_HEIGHT 0x01000010 /* readonly */ ++#define XINE_PARAM_VO_SHARPNESS 0x01000018 /* 0..65535 */ ++#define XINE_PARAM_VO_NOISE_REDUCTION 0x01000019 /* 0..65535 */ + #define XINE_PARAM_VO_CROP_LEFT 0x01000020 /* crop frame pixels */ + #define XINE_PARAM_VO_CROP_RIGHT 0x01000021 /* crop frame pixels */ + #define XINE_PARAM_VO_CROP_TOP 0x01000022 /* crop frame pixels */ + #define XINE_PARAM_VO_CROP_BOTTOM 0x01000023 /* crop frame pixels */ + +- + #define XINE_VO_ZOOM_STEP 100 + #define XINE_VO_ZOOM_MAX 400 + #define XINE_VO_ZOOM_MIN -85 +@@ -483,6 +484,7 @@ int xine_get_current_frame_data (xine_s + #define XINE_IMGFMT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y') + #define XINE_IMGFMT_XVMC (('C'<<24)|('M'<<16)|('v'<<8)|'X') + #define XINE_IMGFMT_XXMC (('C'<<24)|('M'<<16)|('x'<<8)|'X') ++#define XINE_IMGFMT_VDPAU (('A'<<24)|('P'<<16)|('D'<<8)|'V') + + /* get current xine's virtual presentation timestamp (1/90000 sec) + * note: this is mostly internal data. +@@ -1447,6 +1449,27 @@ typedef struct { + #endif /* WIN32 */ + + /* ++ * frame structure used for grabbing raw RGB output frames ++ */ ++typedef struct { ++ /* Cropping of source image */ ++ int crop_left; ++ int crop_right; ++ int crop_top; ++ int crop_bottom; ++ ++ /* Parameters of returned image */ ++ int width; ++ int height; ++ uint8_t *img; ++ uint64_t vpts; ++ ++ int timeout; /* Max. time to wait for next frame in milliseconds */ ++ ++} xine_grab_frame_t; ++ ++ ++/* + * "type" constants for xine_port_send_gui_data(...) + */ + +@@ -1475,6 +1498,18 @@ typedef struct { + /* Gui is about to destroy drawable */ + #define XINE_GUI_SEND_WILL_DESTROY_DRAWABLE 9 + ++/* Allocate grab frame */ ++/* xine_grab_frame_t **data */ ++#define XINE_GUI_SEND_ALLOC_GRAB_FRAME 10 ++ ++/* Free grab frame */ ++/* xine_grab_frame_t *data */ ++#define XINE_GUI_SEND_FREE_GRAB_FRAME 11 ++ ++/* Grab image of last displayed frame */ ++/* xine_grab_frame_t *data */ ++#define XINE_GUI_SEND_GRAB_FRAME 12 ++ + + /********************************************************************* + * xine health check stuff * +@@ -2169,8 +2204,11 @@ void xine_event_send (xine_stream_t *str + /* yellow text, black border, transparent background */ + #define XINE_TEXTPALETTE_YELLOW_BLACK_TRANSPARENT 3 + +-#define XINE_OSD_CAP_FREETYPE2 0x0001 /* freetype2 support compiled in */ +-#define XINE_OSD_CAP_UNSCALED 0x0002 /* unscaled overlays supp. by vo drv */ ++#define XINE_OSD_CAP_FREETYPE2 0x0001 /* freetype2 support compiled in */ ++#define XINE_OSD_CAP_UNSCALED 0x0002 /* unscaled overlays supp. by vo drv */ ++#define XINE_OSD_CAP_CUSTOM_EXTENT 0x0004 /* hardware scaled to match video output window */ ++#define XINE_OSD_CAP_ARGB_LAYER 0x0008 /* supports separate true color layer */ ++#define XINE_OSD_CAP_VIDEO_WINDOW 0x0010 /* can scale video to an area within osd extent */ + + typedef struct xine_osd_s xine_osd_t; + +@@ -2235,6 +2273,35 @@ void xine_osd_get_palette (xine + void xine_osd_set_palette (xine_osd_t *self, + const uint32_t *const color, + const uint8_t *const trans ) XINE_PROTECTED; ++ ++/* ++ * set an argb buffer to be blended into video ++ * the buffer must exactly match the osd dimensions ++ * and stay valid while the osd is on screen. pass ++ * a NULL pointer to safely remove the buffer from ++ * the osd layer. only the dirty area will be ++ * updated on screen. for convinience the whole ++ * osd object will be considered dirty when setting ++ * a different buffer pointer. ++ * see also XINE_OSD_CAP_ARGB_LAYER ++ */ ++void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer, ++ int dirty_x, int dirty_y, int dirty_width, int dirty_height) XINE_PROTECTED; ++ ++/* ++ * define extent of reference coordinate system ++ * for video resolution independent osds. ++ * see also XINE_OSD_CAP_CUSTOM_EXTENT ++ */ ++void xine_osd_set_extent(xine_osd_t *self, int extent_width, int extent_height) XINE_PROTECTED; ++ ++/* ++ * define area within osd extent to output ++ * video to while osd is on screen ++ * see also XINE_OSD_CAP_VIDEO_WINDOW ++ */ ++void xine_osd_set_video_window(xine_osd_t *self, int window_x, int window_y, int window_width, int window_height) XINE_PROTECTED; ++ + /* + * close osd rendering engine + * loaded fonts are unloaded +--- xine-lib-1.1.19.orig/include/configure.h.in ++++ xine-lib-1.1.19/include/configure.h.in +@@ -113,7 +113,7 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_ASSERT_H + +-/* Define to 1 if `output_muted' is a member of `audio_info_t'. */ ++/* Define to 1 if `audio_info_t' is a member of `output_muted'. */ + #undef HAVE_AUDIO_INFO_T_OUTPUT_MUTED + + /* Define to 1 if you have the `basename' function. */ +@@ -530,6 +530,9 @@ + /* Define this if you use external libcdio/libvcdinfo */ + #undef HAVE_VCDNAV + ++/* Define to 1 if you have the header file. */ ++#undef HAVE_VDPAU_VDPAU_X11_H ++ + /* Define 1 if you have vldXvMC.h */ + #undef HAVE_VLDXVMC + +@@ -669,8 +672,9 @@ + /* Define to 1 if you have the ANSI C header files. */ + #undef STDC_HEADERS + +-/* Define this if the compiler supports __attribute__(( ifelse([weak, alias], +- , [alias], [weak, alias]) )) */ ++/* Define this if the compiler supports __attribute__(( ++ ifelse([weak,], [ ], [79])[][]_m4_text_wrap_word([alias], , [alias], ++ [weak,], [ ], [79])[][]_m4_text_wrap_word([alias]) )) */ + #undef SUPPORT_ATTRIBUTE_ALIAS + + /* Define this if the compiler supports __attribute__(( ifelse([], , [const], +@@ -681,8 +685,11 @@ + [deprecated], []) )) */ + #undef SUPPORT_ATTRIBUTE_DEPRECATED + +-/* Define this if the compiler supports __attribute__(( ifelse([format(printf, +- n, n)], , [format], [format(printf, n, n)]) )) */ ++/* Define this if the compiler supports __attribute__(( ++ ifelse([format(printf,], [ ], [79])[][]_m4_text_wrap_word([n,], [ ], [79])[][]_m4_text_wrap_word([n)], ++ , [format], ++ [format(printf,], [ ], [79])[][]_m4_text_wrap_word([n,], [ ], [79])[][]_m4_text_wrap_word([n)]) ++ )) */ + #undef SUPPORT_ATTRIBUTE_FORMAT + + /* Define this if the compiler supports __attribute__(( --- /dev/null 2011-01-15 00:00:00.000000000 +0100 +++ files/post-patch-vdpau-configure.ac 2011-01-12 22:46:01.000000000 +0100 @@ -0,0 +1,11 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -2528,7 +2528,7 @@ makeexpand () { + + xinelibdir='${libdir}/xine' + xinedatadir='${datadir}/xine' +-pkgconfigdir='${libdir}/pkgconfig' ++pkgconfigdir='${prefix}/libdata/pkgconfig' + AC_SUBST(xinelibdir) + AC_SUBST(xinedatadir) + AC_SUBST(pkgconfigdir) Index: files/post-patch-vdpau-src-vdr-input_vdr.c @@ -0,0 +1,12 @@ +--- a/src/vdr/input_vdr.c ++++ b/src/vdr/input_vdr.c +@@ -32,6 +32,9 @@ + #include + #include + ++#ifdef __FreeBSD__ ++#include ++#endif + #include + #include + #include