Merge from 1.1; merge vdpau (with adjustments for 1.2).
authorDarren Salt <linux@youmustbejoking.demon.co.uk>
Fri, 20 Nov 2009 03:46:10 +0000
changeset 113359b68f6efb713
parent 11012 7af2793bc117
parent 11334 2981a23899cc
child 11336 370dc5d5f8c8
child 11344 146659fc6615
Merge from 1.1; merge vdpau (with adjustments for 1.2).
ChangeLog
configure.ac
include/xine.h
include/xine/osd.h
include/xine/video_out.h
m4/summary.m4
m4/video_out.m4
src/Makefile.am
src/demuxers/Makefile.am
src/demuxers/demux_mpeg.c
src/demuxers/demux_vc1es.c
src/input/http_helper.c
src/libvdpau/Makefile.am
src/libvdpau/bits_reader.h
src/libvdpau/dpb.c
src/libvdpau/dpb.h
src/libvdpau/h264_parser.c
src/libvdpau/h264_parser.h
src/libvdpau/nal.c
src/libvdpau/nal.h
src/libvdpau/vdpau_h264.c
src/libvdpau/vdpau_mpeg12.c
src/libvdpau/vdpau_vc1.c
src/spu_dec/spudvb_decoder.c
src/video_dec/Makefile.am
src/video_dec/libvdpau/Makefile.am
src/video_dec/libvdpau/bits_reader.h
src/video_dec/libvdpau/dpb.c
src/video_dec/libvdpau/dpb.h
src/video_dec/libvdpau/h264_parser.c
src/video_dec/libvdpau/h264_parser.h
src/video_dec/libvdpau/nal.c
src/video_dec/libvdpau/nal.h
src/video_dec/libvdpau/vdpau_h264.c
src/video_dec/libvdpau/vdpau_mpeg12.c
src/video_dec/libvdpau/vdpau_vc1.c
src/video_out/Makefile.am
src/video_out/video_out_raw.c
src/video_out/video_out_vdpau.c
src/video_out/video_out_xv.c
src/xine-engine/load_plugins.c
src/xine-engine/osd.c
src/xine-engine/video_out.c
src/xine-engine/xine.c
src/xine-engine/xine_interface.c
     1.1 --- a/ChangeLog	Thu Nov 19 15:29:17 2009 +0000
     1.2 +++ b/ChangeLog	Fri Nov 20 03:46:10 2009 +0000
     1.3 @@ -1,5 +1,6 @@
     1.4  xine-lib (1.1.90) (Unreleased)
     1.5    * Add support for VDR.
     1.6 +  * Add support for VDPAU.
     1.7    * xine-config is deprecated in favour of pkg-config libxine.
     1.8      Use "pkgconfig --variable=foo libxine" where you previously used
     1.9      "xine-config --foo".
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/README-VDPAU	Fri Nov 20 03:46:10 2009 +0000
     2.3 @@ -0,0 +1,70 @@
     2.4 +xine-vdpau README:
     2.5 +------------------------------------------------------------------------------
     2.6 +
     2.7 +So, you want to give it a try, but wonder which steps are required.
     2.8 +Ok, so here it is:
     2.9 +
    2.10 +0) you need nvidia's driver 180.22 or later.
    2.11 +
    2.12 +1) get the sources:
    2.13 +svn co svn://jusst.de/xine-vdpau
    2.14 +
    2.15 +2) compile the sources:
    2.16 +cd xine-vdpau
    2.17 +./autogen.sh
    2.18 +./configure
    2.19 +make
    2.20 +make install (as root)
    2.21 +    **(make sure that no other xine-lib installation will conflict with this one)
    2.22 +
    2.23 +3) edit your xine configuration
    2.24 +nano $HOME/.xine/config (if it does not exist, first run "xine --no-logo" then quit.
    2.25 +search for "engine.buffers.video_num_frames" and set it to 22
    2.26 +
    2.27 +4) running the beast:
    2.28 +xine -verbose /path/to/a/working/sample
    2.29 +    ** --verbose will print some usefull things in your console (in case of problems,
    2.30 +        the developers will ask you to give this output, at least)
    2.31 +
    2.32 +5) update your svn copy quite often
    2.33 +
    2.34 +6) don't blame us if it crashes, burn you gpu (unlikely:) or anything else.
    2.35 +
    2.36 +
    2.37 +------------------------------------------------------------------------------
    2.38 +
    2.39 +FAQ:
    2.40 +
    2.41 +Q:
    2.42 +  Why my file plays fine with mplayer-vdpau and not with xine-vdpau?
    2.43 +A:
    2.44 +  We are not using the nvidia's libavcodec patch.
    2.45 +  We are writing decoders from scratch.
    2.46 +  So don't expect them to be as mature as ffmpeg ones. Not yet.
    2.47 +
    2.48 +Q:
    2.49 +  Why mpeg2 doesn't use less cpu than software decoder?
    2.50 +A:
    2.51 +  Because at that moment it does a lot of memcpy. This will be fixed soon, but that's not
    2.52 +  a priority. Stability is our focus.
    2.53 +
    2.54 +Q:
    2.55 +  Is deinterlacing working?
    2.56 +A:
    2.57 +  Yes. It's already quite good (doing 50i->50p), but could even be better in the future.
    2.58 +
    2.59 +Q:
    2.60 +  How do i get it working with VDR, Kaffeine, whatever.
    2.61 +A:
    2.62 +  Ask VDR, Kaffeine, whatever developers.
    2.63 +    (Note: for kaffeine you are lucky, i'm going to tell you the tip.
    2.64 +     Build kaffeine like that: ./configure --without-xcb && make && make install)
    2.65 +
    2.66 +Q:
    2.67 +  How can i contact you?
    2.68 +A:
    2.69 +  IRC: #xine-vdpau on freenode
    2.70 +  MAIL: http://lists.kafic.ba/mailman/listinfo/xine-vdpau
    2.71 +  Eventually, nvnews.
    2.72 +
    2.73 +----------------------------------------------------------------------------
     3.1 --- a/configure.ac	Thu Nov 19 15:29:17 2009 +0000
     3.2 +++ b/configure.ac	Fri Nov 20 03:46:10 2009 +0000
     3.3 @@ -1265,6 +1265,7 @@
     3.4  src/video_dec/libmpeg2new/Makefile
     3.5  src/video_dec/libmpeg2new/include/Makefile
     3.6  src/video_dec/libmpeg2new/libmpeg2/Makefile
     3.7 +src/video_dec/libvdpau/Makefile
     3.8  src/video_out/Makefile
     3.9  src/video_out/macosx/Makefile
    3.10  src/xine-utils/Makefile
     4.1 --- a/include/xine.h	Thu Nov 19 15:29:17 2009 +0000
     4.2 +++ b/include/xine.h	Fri Nov 20 03:46:10 2009 +0000
     4.3 @@ -342,12 +342,13 @@
     4.4  #define XINE_PARAM_VO_TVMODE               0x0100000a /* ???                */
     4.5  #define XINE_PARAM_VO_WINDOW_WIDTH         0x0100000f /* readonly           */
     4.6  #define XINE_PARAM_VO_WINDOW_HEIGHT        0x01000010 /* readonly           */
     4.7 +#define XINE_PARAM_VO_SHARPNESS            0x01000018 /* 0..65535           */
     4.8 +#define XINE_PARAM_VO_NOISE_REDUCTION      0x01000019 /* 0..65535           */
     4.9  #define XINE_PARAM_VO_CROP_LEFT            0x01000020 /* crop frame pixels  */
    4.10  #define XINE_PARAM_VO_CROP_RIGHT           0x01000021 /* crop frame pixels  */
    4.11  #define XINE_PARAM_VO_CROP_TOP             0x01000022 /* crop frame pixels  */
    4.12  #define XINE_PARAM_VO_CROP_BOTTOM          0x01000023 /* crop frame pixels  */
    4.13  
    4.14 -
    4.15  #define XINE_VO_ZOOM_STEP                  100
    4.16  #define XINE_VO_ZOOM_MAX                   400
    4.17  #define XINE_VO_ZOOM_MIN                   -85
    4.18 @@ -449,6 +450,7 @@
    4.19  #define XINE_IMGFMT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y')
    4.20  #define XINE_IMGFMT_XVMC (('C'<<24)|('M'<<16)|('v'<<8)|'X')
    4.21  #define XINE_IMGFMT_XXMC (('C'<<24)|('M'<<16)|('x'<<8)|'X')
    4.22 +#define XINE_IMGFMT_VDPAU (('A'<<24)|('P'<<16)|('D'<<8)|'V')
    4.23  
    4.24  /* get current xine's virtual presentation timestamp (1/90000 sec)
    4.25   * note: this is mostly internal data.
    4.26 @@ -2080,9 +2082,9 @@
    4.27  
    4.28  #define XINE_OSD_CAP_FREETYPE2     0x0001 /* freetype2 support compiled in     */
    4.29  #define XINE_OSD_CAP_UNSCALED      0x0002 /* unscaled overlays supp. by vo drv */
    4.30 -#define XINE_OSD_CAP_CUSTOM_EXTENT 0x0004 /* hardware scaled to match video output window */ 
    4.31 +#define XINE_OSD_CAP_CUSTOM_EXTENT 0x0004 /* hardware scaled to match video output window */
    4.32  #define XINE_OSD_CAP_ARGB_LAYER    0x0008 /* supports separate true color layer */
    4.33 -#define XINE_OSD_CAP_VIDEO_WINDOW  0x0010 /* can scale video to an area within osd extent */ 
    4.34 +#define XINE_OSD_CAP_VIDEO_WINDOW  0x0010 /* can scale video to an area within osd extent */
    4.35  
    4.36  typedef struct xine_osd_s xine_osd_t;
    4.37  
    4.38 @@ -2147,7 +2149,7 @@
    4.39  void        xine_osd_set_palette   (xine_osd_t *self,
    4.40  				    const uint32_t *const color,
    4.41  				    const uint8_t *const trans ) XINE_PROTECTED;
    4.42 -				    
    4.43 +
    4.44  /*
    4.45   * set an argb buffer to be blended into video
    4.46   * the buffer must exactly match the osd dimensions
     5.1 --- a/include/xine/video_out.h	Thu Nov 19 15:29:17 2009 +0000
     5.2 +++ b/include/xine/video_out.h	Fri Nov 20 03:46:10 2009 +0000
     5.3 @@ -154,6 +154,9 @@
     5.4    
     5.5    /* displacement for overlays */
     5.6    int                       overlay_offset_x, overlay_offset_y;
     5.7 +
     5.8 +  /* pointer to the next frame in display order, used by some vo deint */
     5.9 +  struct vo_frame_s         *future_frame;
    5.10    
    5.11    /* 
    5.12     * that part is used only by video_out.c for frame management
    5.13 @@ -255,7 +258,9 @@
    5.14  #define VO_PROP_OUTPUT_HEIGHT         20 /* read-only */
    5.15  #define VO_PROP_OUTPUT_XOFFSET        21 /* read-only */
    5.16  #define VO_PROP_OUTPUT_YOFFSET        22 /* read-only */
    5.17 -#define VO_NUM_PROPERTIES             23
    5.18 +#define VO_PROP_SHARPNESS             24
    5.19 +#define VO_PROP_NOISE_REDUCTION       25
    5.20 +#define VO_NUM_PROPERTIES             26
    5.21  
    5.22  /* number of colors in the overlay palette. Currently limited to 256
    5.23     at most, because some alphablend functions use an 8-bit index into
    5.24 @@ -277,6 +282,7 @@
    5.25  #define VO_PAN_SCAN_FLAG     4
    5.26  #define VO_INTERLACED_FLAG   8
    5.27  #define VO_NEW_SEQUENCE_FLAG 16 /* set after MPEG2 Sequence Header Code (used by XvMC) */
    5.28 +#define VO_CHROMA_422        32 /* used by VDPAU, default is chroma_420 */
    5.29  
    5.30  /* video driver capabilities */
    5.31  #define VO_CAP_YV12                   0x00000001 /* driver can handle YUV 4:2:0 pictures */
    5.32 @@ -286,6 +292,9 @@
    5.33  #define VO_CAP_UNSCALED_OVERLAY       0x00000010 /* driver can blend overlay at output resolution */
    5.34  #define VO_CAP_CROP                   0x00000020 /* driver can crop */
    5.35  #define VO_CAP_XXMC                   0x00000040 /* driver can use extended XvMC */
    5.36 +#define VO_CAP_VDPAU_H264             0x00000080 /* driver can use VDPAU for H264 */
    5.37 +#define VO_CAP_VDPAU_MPEG12           0x00000100 /* driver can use VDPAU for mpeg1/2 */
    5.38 +#define VO_CAP_VDPAU_VC1              0x00000200 /* driver can use VDPAU for mpeg1/2 */
    5.39  #define VO_CAP_HUE                    0x00010000
    5.40  #define VO_CAP_SATURATION             0x00020000
    5.41  #define VO_CAP_CONTRAST               0x00040000
    5.42 @@ -298,6 +307,7 @@
    5.43  #define VO_CAP_ARGB_LAYER_OVERLAY     0x02000000 /* driver supports true color overlay */
    5.44  #define VO_CAP_VIDEO_WINDOW_OVERLAY   0x04000000 /* driver can scale video to an area within overlay */
    5.45  
    5.46 +
    5.47  /*
    5.48   * vo_driver_s contains the functions every display driver
    5.49   * has to implement. The vo_new_port function (see below)
    5.50 @@ -468,7 +478,6 @@
    5.51    
    5.52    int               unscaled;      /* true if it should be blended unscaled */
    5.53  
    5.54 -
    5.55    argb_layer_t     *argb_layer;
    5.56  };
    5.57  
     6.1 --- a/m4/summary.m4	Thu Nov 19 15:29:17 2009 +0000
     6.2 +++ b/m4/summary.m4	Fri Nov 20 03:46:10 2009 +0000
     6.3 @@ -78,6 +78,7 @@
     6.4      test x"$have_imagemagick" = x"yes" && echo "   - image"
     6.5      test x"$have_theora" = x"yes"      && echo "   - theora"
     6.6      test x"$have_w32dll" = x"yes"      && echo "   - w32dll"
     6.7 +    test x$"have_vdpau" = x"yes"       && echo "   - vdpau"
     6.8      if test x"$with_external_ffmpeg" != x"no"; then
     6.9          echo "   - ffmpeg (external library)"
    6.10      else
    6.11 @@ -203,6 +204,7 @@
    6.12                  echo "   - OpenGL"
    6.13              fi
    6.14          fi
    6.15 +        test x$"have_vdpau" = x"yes"       && echo "   - vdpau (X11 VDPAU)"
    6.16          if test x"$have_sunfb" = x"yes"; then
    6.17              if test x"$have_sundga" = x"yes"; then
    6.18                  echo "   - PGX64 (for Sun XVR100/PGX64/PGX24 cards)"
     7.1 --- a/m4/video_out.m4	Thu Nov 19 15:29:17 2009 +0000
     7.2 +++ b/m4/video_out.m4	Fri Nov 20 03:46:10 2009 +0000
     7.3 @@ -499,4 +499,20 @@
     7.4      fi
     7.5      AM_CONDITIONAL([ENABLE_XVMC], [test x"$have_xvmc" = x"yes"])
     7.6      AM_CONDITIONAL([ENABLE_XXMC], [test x"$have_xxmc" = x"yes"])
     7.7 -])dnl XINE_VIDEO_OUT_PLUGINS
     7.8 +
     7.9 +
    7.10 +    dnl VDPAU
    7.11 +    AC_ARG_ENABLE([vdpau], [AS_HELP_STRING([--disable-vdpau], [Disable VDPAU output plugin])])
    7.12 +    if test x"$no_x" != x"yes" && test x"$enable_vdpau" != x"no"; then
    7.13 +        AC_CHECK_HEADERS([vdpau/vdpau_x11.h], [have_vdpau=yes], [have_vdpau=no])
    7.14 +        if test x"$have_vdpau" = x"yes"; then
    7.15 +            AC_CHECK_LIB([vdpau], [vdp_device_create_x11], [], [have_vdpau=no], [$X_LIBS $X_PRE_LIBS -lXext $X_EXTRA_LIBS])
    7.16 +        fi
    7.17 +        if test x"$enable_vdpau" = x"yes" && test x"$have_vdpau" != x"yes"; then
    7.18 +            AC_MSG_ERROR([VDPAU support requested, but not all requirements are met])
    7.19 +        fi
    7.20 +    fi
    7.21 +    AM_CONDITIONAL([ENABLE_VDPAU], test x"$have_vdpau" = x"yes")
    7.22 +    
    7.23 +])dnl XINE_VIDEO_OUT_PLUGIN
    7.24 +S
     8.1 --- a/src/demuxers/Makefile.am	Thu Nov 19 15:29:17 2009 +0000
     8.2 +++ b/src/demuxers/Makefile.am	Fri Nov 20 03:46:10 2009 +0000
     8.3 @@ -52,7 +52,8 @@
     8.4  	xineplug_dmx_matroska.la \
     8.5  	xineplug_dmx_iff.la \
     8.6  	xineplug_dmx_flv.la \
     8.7 -	xineplug_dmx_playlist.la
     8.8 +	xineplug_dmx_playlist.la \
     8.9 +	xineplug_dmx_vc1_es.la
    8.10  
    8.11  xineplug_dmx_avi_la_SOURCES = demux_avi.c
    8.12  xineplug_dmx_avi_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
    8.13 @@ -67,6 +68,9 @@
    8.14  xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c
    8.15  xineplug_dmx_mpeg_elem_la_LIBADD = $(XINE_LIB)
    8.16  
    8.17 +xineplug_dmx_vc1_es_la_SOURCES = demux_vc1es.c
    8.18 +xineplug_dmx_vc1_es_la_LIBADD = $(XINE_LIB)
    8.19 +
    8.20  xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c
    8.21  xineplug_dmx_mpeg_pes_la_CFLAGS = $(AM_CFLAGS) $(AVUTIL_CFLAGS)
    8.22  xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) $(AVUTIL_LIBS)
     9.1 --- a/src/demuxers/demux_mpeg.c	Thu Nov 19 15:29:17 2009 +0000
     9.2 +++ b/src/demuxers/demux_mpeg.c	Fri Nov 20 03:46:10 2009 +0000
     9.3 @@ -246,6 +246,8 @@
     9.4  
     9.5    len = read_bytes(this, 2);
     9.6  
     9.7 +  //printf( "parse_mpeg2_packet: stream_id=%X\n", stream_id);
     9.8 +
     9.9    if (stream_id==0xbd) {
    9.10  
    9.11      int track;
    9.12 @@ -483,7 +485,7 @@
    9.13  
    9.14      }
    9.15  
    9.16 -  } else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) {
    9.17 +  } else if ( ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) || stream_id==0xfd ) {
    9.18  
    9.19      w = read_bytes(this, 1);
    9.20      flags = read_bytes(this, 1);
    9.21 @@ -532,7 +534,7 @@
    9.22  	return;
    9.23        }
    9.24  
    9.25 -      buf->type = BUF_VIDEO_MPEG;
    9.26 +      buf->type = (stream_id==0xfd) ? BUF_VIDEO_VC1 : BUF_VIDEO_MPEG;
    9.27        buf->pts  = pts;
    9.28        buf->decoder_info[0] = pts - dts;
    9.29        check_newpts( this, pts, PTS_VIDEO );
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/demuxers/demux_vc1es.c	Fri Nov 20 03:46:10 2009 +0000
    10.3 @@ -0,0 +1,406 @@
    10.4 +/*
    10.5 + * Copyright (C) 2008 the xine project
    10.6 + * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
    10.7 + *
    10.8 + * This file is part of xine, a free video player.
    10.9 + *
   10.10 + * xine is free software; you can redistribute it and/or modify
   10.11 + * it under the terms of the GNU General Public License as published by
   10.12 + * the Free Software Foundation; either version 2 of the License, or
   10.13 + * (at your option) any later version.
   10.14 + *
   10.15 + * xine is distributed in the hope that it will be useful,
   10.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.18 + * GNU General Public License for more details.
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License
   10.21 + * along with this program; if not, write to the Free Software
   10.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   10.23 + */
   10.24 +
   10.25 +/*
   10.26 + * demultiplexer for wmv9/vc1 elementary streams
   10.27 + *
   10.28 + *
   10.29 + *    SMP (.rcv) format:
   10.30 + *
   10.31 + *    ** header ***
   10.32 + *    le24 number of frames
   10.33 + *    C5 04 00 00 00
   10.34 + *    4 bytes sequence header
   10.35 + *    le32 height
   10.36 + *    le32 width
   10.37 + *    0C 00 00 00
   10.38 + *    8 bytes unknown
   10.39 + *    le32 fps
   10.40 + *    ************
   10.41 + *    le24 frame_size
   10.42 + *    80
   10.43 + *    le32 pts (ms)
   10.44 + *    frame_size bytes of picture data
   10.45 + */
   10.46 +
   10.47 +#ifdef HAVE_CONFIG_H
   10.48 +#include "config.h"
   10.49 +#endif
   10.50 +
   10.51 +#include <stdio.h>
   10.52 +#include <stdlib.h>
   10.53 +#include <fcntl.h>
   10.54 +#include <unistd.h>
   10.55 +#include <string.h>
   10.56 +
   10.57 +/* #define LOG */
   10.58 +#define LOG_MODULE "demux_vc1es"
   10.59 +#define LOG_VERBOSE
   10.60 +
   10.61 +#include <xine/xine_internal.h>
   10.62 +#include <xine/xineutils.h>
   10.63 +#include <xine/compat.h>
   10.64 +#include <xine/demux.h>
   10.65 +#include "bswap.h"
   10.66 +
   10.67 +#define SCRATCH_SIZE 36
   10.68 +#define PRIVATE_SIZE 44
   10.69 +
   10.70 +#define MODE_SMP 1
   10.71 +#define MODE_AP  2
   10.72 +
   10.73 +
   10.74 +
   10.75 +typedef struct {
   10.76 +  demux_plugin_t      demux_plugin;
   10.77 +
   10.78 +  xine_stream_t       *stream;
   10.79 +  fifo_buffer_t       *video_fifo;
   10.80 +  fifo_buffer_t       *audio_fifo;
   10.81 +  input_plugin_t      *input;
   10.82 +  int                  status;
   10.83 +  int                  mode;
   10.84 +  int                  first_chunk;
   10.85 +  uint8_t              private[PRIVATE_SIZE];
   10.86 +  uint32_t             video_step;
   10.87 +
   10.88 +  uint32_t             blocksize;
   10.89 +} demux_vc1_es_t ;
   10.90 +
   10.91 +
   10.92 +
   10.93 +typedef struct {
   10.94 +  demux_class_t     demux_class;
   10.95 +} demux_vc1_es_class_t;
   10.96 +
   10.97 +
   10.98 +
   10.99 +static int demux_vc1_es_next_smp( demux_vc1_es_t *this )
  10.100 +{
  10.101 +  buf_element_t *buf;
  10.102 +  uint32_t pts=0, frame_size=0;
  10.103 +  off_t done;
  10.104 +  uint8_t head[SCRATCH_SIZE];
  10.105 +  int start_flag = 1;
  10.106 +
  10.107 +  if ( this->first_chunk ) {
  10.108 +    this->input->read( this->input, head, SCRATCH_SIZE );
  10.109 +    this->first_chunk = 0;
  10.110 +  }
  10.111 +
  10.112 +  done = this->input->read( this->input, head, 8 );
  10.113 +  frame_size = _X_LE_24( head );
  10.114 +  pts = _X_LE_32( head+4 );
  10.115 +
  10.116 +  done = 0;
  10.117 +  while ( frame_size>0 ) {
  10.118 +    buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
  10.119 +    off_t read = (frame_size>buf->max_size) ? buf->max_size : frame_size;
  10.120 +    done = this->input->read( this->input, buf->mem, read );
  10.121 +    if ( done<=0 ) {
  10.122 +      buf->free_buffer( buf );
  10.123 +      this->status = DEMUX_FINISHED;
  10.124 +      return 0;
  10.125 +    }
  10.126 +    buf->size = done;
  10.127 +    buf->content = buf->mem;
  10.128 +    buf->type = BUF_VIDEO_WMV9;
  10.129 +    buf->pts = pts*90;
  10.130 +    frame_size -= done;
  10.131 +    if ( start_flag ) {
  10.132 +      buf->decoder_flags = BUF_FLAG_FRAME_START;
  10.133 +      start_flag = 0;
  10.134 +    }
  10.135 +    if ( !(frame_size>0) )
  10.136 +      buf->decoder_flags = BUF_FLAG_FRAME_END;
  10.137 +    this->video_fifo->put(this->video_fifo, buf);
  10.138 +  }
  10.139 +
  10.140 +  return 1;
  10.141 +}
  10.142 +
  10.143 +
  10.144 +
  10.145 +static int demux_vc1_es_next_ap( demux_vc1_es_t *this )
  10.146 +{
  10.147 +  buf_element_t *buf;
  10.148 +  uint32_t blocksize;
  10.149 +  off_t done;
  10.150 +
  10.151 +  buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
  10.152 +  blocksize = (this->blocksize ? this->blocksize : buf->max_size);
  10.153 +  done = this->input->read(this->input, buf->mem, blocksize);
  10.154 +
  10.155 +  if (done <= 0) {
  10.156 +    buf->free_buffer (buf);
  10.157 +    this->status = DEMUX_FINISHED;
  10.158 +    return 0;
  10.159 +  }
  10.160 +
  10.161 +  buf->size = done;
  10.162 +  buf->content = buf->mem;
  10.163 +  buf->pts = 0;
  10.164 +  buf->type = BUF_VIDEO_VC1;
  10.165 +
  10.166 +  if( this->input->get_length (this->input) )
  10.167 +    buf->extra_info->input_normpos = (int)( (double)this->input->get_current_pos( this->input )*65535/this->input->get_length( this->input ) );
  10.168 +
  10.169 +  this->video_fifo->put(this->video_fifo, buf);
  10.170 +
  10.171 +  return 1;
  10.172 +}
  10.173 +
  10.174 +
  10.175 +
  10.176 +static int demux_vc1_es_send_chunk( demux_plugin_t *this_gen )
  10.177 +{
  10.178 +  demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen;
  10.179 +
  10.180 +  if ( this->mode==MODE_SMP ) {
  10.181 +    if (!demux_vc1_es_next_smp(this))
  10.182 +      this->status = DEMUX_FINISHED;
  10.183 +    return this->status;
  10.184 +  }
  10.185 +
  10.186 +  if (!demux_vc1_es_next_ap(this))
  10.187 +    this->status = DEMUX_FINISHED;
  10.188 +  return this->status;
  10.189 +}
  10.190 +
  10.191 +
  10.192 +
  10.193 +static int demux_vc1_es_get_status( demux_plugin_t *this_gen )
  10.194 +{
  10.195 +  demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen;
  10.196 +
  10.197 +  return this->status;
  10.198 +}
  10.199 +
  10.200 +
  10.201 +
  10.202 +static void demux_vc1_es_send_headers( demux_plugin_t *this_gen )
  10.203 +{
  10.204 +  demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen;
  10.205 +
  10.206 +  this->video_fifo  = this->stream->video_fifo;
  10.207 +  this->audio_fifo  = this->stream->audio_fifo;
  10.208 +  _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
  10.209 +  _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 0);
  10.210 +  _x_demux_control_start(this->stream);
  10.211 +  this->blocksize = this->input->get_blocksize(this->input);
  10.212 +  this->status = DEMUX_OK;
  10.213 +
  10.214 +  if ( this->mode==MODE_SMP ) {
  10.215 +    buf_element_t *buf;
  10.216 +    buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
  10.217 +    xine_fast_memcpy( buf->mem, this->private, PRIVATE_SIZE );
  10.218 +    buf->size = PRIVATE_SIZE;
  10.219 +    buf->content = buf->mem;
  10.220 +    buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
  10.221 +    if ( this->video_step ) {
  10.222 +      buf->decoder_flags |= BUF_FLAG_FRAMERATE;
  10.223 +      buf->decoder_info[0] = 90000/this->video_step;
  10.224 +    }
  10.225 +    buf->type = BUF_VIDEO_WMV9;
  10.226 +    this->video_fifo->put(this->video_fifo, buf);
  10.227 +  }
  10.228 +}
  10.229 +
  10.230 +
  10.231 +
  10.232 +static int demux_vc1_es_seek( demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing )
  10.233 +{
  10.234 +  demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen;
  10.235 +
  10.236 +  if ( this->mode==MODE_SMP ) {
  10.237 +    this->status = DEMUX_OK;
  10.238 +    return this->status;
  10.239 +  }
  10.240 +
  10.241 +  start_pos = (off_t) ( (double) start_pos / 65535 *
  10.242 +              this->input->get_length (this->input) );
  10.243 +
  10.244 +  this->status = DEMUX_OK;
  10.245 +
  10.246 +  if (playing)
  10.247 +    _x_demux_flush_engine(this->stream);
  10.248 +
  10.249 +  if (INPUT_IS_SEEKABLE(this->input)) {
  10.250 +
  10.251 +    /* FIXME: implement time seek */
  10.252 +
  10.253 +    if (start_pos != this->input->seek (this->input, start_pos, SEEK_SET)) {
  10.254 +      this->status = DEMUX_FINISHED;
  10.255 +      return this->status;
  10.256 +    }
  10.257 +    lprintf ("seeking to %"PRId64"\n", start_pos);
  10.258 +  }
  10.259 +
  10.260 +  /*
  10.261 +   * now start demuxing
  10.262 +   */
  10.263 +  this->status = DEMUX_OK;
  10.264 +
  10.265 +  return this->status;
  10.266 +}
  10.267 +
  10.268 +
  10.269 +
  10.270 +static void demux_vc1_es_dispose( demux_plugin_t *this )
  10.271 +{
  10.272 +  free (this);
  10.273 +}
  10.274 +
  10.275 +
  10.276 +
  10.277 +static int demux_vc1_es_get_stream_length( demux_plugin_t *this_gen )
  10.278 +{
  10.279 +  return 0 ; /*FIXME: implement */
  10.280 +}
  10.281 +
  10.282 +
  10.283 +
  10.284 +static uint32_t demux_vc1_es_get_capabilities( demux_plugin_t *this_gen )
  10.285 +{
  10.286 +  return DEMUX_CAP_NOCAP;
  10.287 +}
  10.288 +
  10.289 +
  10.290 +
  10.291 +static int demux_vc1_es_get_optional_data( demux_plugin_t *this_gen, void *data, int data_type )
  10.292 +{
  10.293 +  return DEMUX_OPTIONAL_UNSUPPORTED;
  10.294 +}
  10.295 +
  10.296 +
  10.297 +
  10.298 +static demux_plugin_t *open_plugin( demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input )
  10.299 +{
  10.300 +
  10.301 +  demux_vc1_es_t *this;
  10.302 +  uint8_t scratch[SCRATCH_SIZE];
  10.303 +  int i, read, found=0;
  10.304 +
  10.305 +  switch (stream->content_detection_method) {
  10.306 +
  10.307 +  case METHOD_BY_CONTENT: {
  10.308 +    read = _x_demux_read_header(input, scratch, SCRATCH_SIZE);
  10.309 +    if (!read)
  10.310 +      return NULL;
  10.311 +    lprintf("read size =%d\n",read);
  10.312 +
  10.313 +    /* simple and main profiles */
  10.314 +    if ( read>=SCRATCH_SIZE ) {
  10.315 +      lprintf("searching for rcv format..\n");
  10.316 +      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 ) {
  10.317 +        lprintf("rcv format found\n");
  10.318 +        found = MODE_SMP;
  10.319 +      }
  10.320 +    }
  10.321 +
  10.322 +    if ( found==0 ) {
  10.323 +      /* advanced profile */
  10.324 +      for (i = 0; i < read-4; i++) {
  10.325 +        lprintf ("%02x %02x %02x %02x\n", scratch[i], scratch[i+1], scratch[i+2], scratch[i+3]);
  10.326 +        if ((scratch[i] == 0x00) && (scratch[i+1] == 0x00) && (scratch[i+2] == 0x01)) {
  10.327 +          if (scratch[i+3] == 0x0f) {
  10.328 +            found = MODE_AP;
  10.329 +            lprintf ("found header at offset 0x%x\n", i);
  10.330 +            break;
  10.331 +          }
  10.332 +        }
  10.333 +      }
  10.334 +    }
  10.335 +
  10.336 +    if (found == 0)
  10.337 +      return NULL;
  10.338 +    lprintf ("input accepted.\n");
  10.339 +  }
  10.340 +  break;
  10.341 +
  10.342 +  case METHOD_BY_MRL:
  10.343 +  case METHOD_EXPLICIT:
  10.344 +  break;
  10.345 +
  10.346 +  default:
  10.347 +    return NULL;
  10.348 +  }
  10.349 +
  10.350 +  this = calloc(1, sizeof(demux_vc1_es_t));
  10.351 +  this->mode = found;
  10.352 +  this->first_chunk = 1;
  10.353 +  if ( found==MODE_SMP ) {
  10.354 +    xine_fast_memcpy( this->private+8, scratch+12, 4 ); /* height */
  10.355 +    xine_fast_memcpy( this->private+4, scratch+16, 4 ); /* width */
  10.356 +    xine_fast_memcpy( this->private+40, scratch+8, 4 ); /* sequence header */
  10.357 +    this->video_step = _X_LE_32( scratch+32 );
  10.358 +  }
  10.359 +  this->stream = stream;
  10.360 +  this->input  = input;
  10.361 +
  10.362 +  this->demux_plugin.send_headers      = demux_vc1_es_send_headers;
  10.363 +  this->demux_plugin.send_chunk        = demux_vc1_es_send_chunk;
  10.364 +  this->demux_plugin.seek              = demux_vc1_es_seek;
  10.365 +  this->demux_plugin.dispose           = demux_vc1_es_dispose;
  10.366 +  this->demux_plugin.get_status        = demux_vc1_es_get_status;
  10.367 +  this->demux_plugin.get_stream_length = demux_vc1_es_get_stream_length;
  10.368 +  this->demux_plugin.get_capabilities  = demux_vc1_es_get_capabilities;
  10.369 +  this->demux_plugin.get_optional_data = demux_vc1_es_get_optional_data;
  10.370 +  this->demux_plugin.demux_class       = class_gen;
  10.371 +
  10.372 +  this->status = DEMUX_FINISHED;
  10.373 +
  10.374 +  return &this->demux_plugin;
  10.375 +}
  10.376 +
  10.377 +
  10.378 +
  10.379 +static void *init_plugin( xine_t *xine, void *data )
  10.380 +{
  10.381 +  demux_vc1_es_class_t     *this;
  10.382 +
  10.383 +  this = calloc(1, sizeof(demux_vc1_es_class_t));
  10.384 +
  10.385 +  this->demux_class.open_plugin     = open_plugin;
  10.386 +  this->demux_class.description     = N_("VC1 elementary stream demux plugin");
  10.387 +  this->demux_class.identifier      = "VC1_ES";
  10.388 +  this->demux_class.mimetypes       = NULL;
  10.389 +  this->demux_class.extensions      = "";
  10.390 +  this->demux_class.dispose         = default_demux_class_dispose;
  10.391 +
  10.392 +  return this;
  10.393 +}
  10.394 +
  10.395 +
  10.396 +/*
  10.397 + * exported plugin catalog entry
  10.398 + */
  10.399 +static const demuxer_info_t demux_info_vc1es = {
  10.400 +  0                       /* priority */
  10.401 +};
  10.402 +
  10.403 +
  10.404 +
  10.405 +const plugin_info_t xine_plugin_info[] EXPORTED = {
  10.406 +  /* type, API, "name", version, special_info, init_function */
  10.407 +  { PLUGIN_DEMUX, 27, "vc1es", XINE_VERSION_CODE, &demux_info_vc1es, init_plugin },
  10.408 +  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
  10.409 +};
    11.1 --- a/src/input/http_helper.c	Thu Nov 19 15:29:17 2009 +0000
    11.2 +++ b/src/input/http_helper.c	Fri Nov 20 03:46:10 2009 +0000
    11.3 @@ -198,6 +198,7 @@
    11.4  	  } else
    11.5  	    *it = start[i];
    11.6  	}
    11.7 +	*it = '\0';
    11.8        }
    11.9      }
   11.10    } else {
    12.1 --- a/src/spu_dec/spudvb_decoder.c	Thu Nov 19 15:29:17 2009 +0000
    12.2 +++ b/src/spu_dec/spudvb_decoder.c	Fri Nov 20 03:46:10 2009 +0000
    12.3 @@ -32,7 +32,11 @@
    12.4  #include <xine/osd.h>
    12.5  #define MAX_REGIONS 7
    12.6  
    12.7 -/*#define LOG 1*/
    12.8 +#define SPU_MAX_WIDTH 720
    12.9 +#define SPU_MAX_HEIGHT 576
   12.10 +
   12.11 +/*#define LOG*/
   12.12 +#define LOG_MODULE "spudvb"
   12.13  
   12.14  typedef struct {
   12.15    int 			x, y;
   12.16 @@ -145,21 +149,17 @@
   12.17    page_t *page = &dvbsub->page;
   12.18  
   12.19    /* reject invalid sizes and set some limits ! */
   12.20 -  if ( region_width<=0 || region_height<=0 || region_width>720 || region_height>576 ) {
   12.21 +  if ( region_width<=0 || region_height<=0 || region_width>SPU_MAX_WIDTH || region_height>SPU_MAX_HEIGHT ) {
   12.22      if ( reg->img ) {
   12.23        free( reg->img );
   12.24        reg->img = NULL;
   12.25      }
   12.26 -#ifdef LOG
   12.27 -    printf("SPUDVB: rejected region %d = %dx%d\n", region_id, region_width, region_height );
   12.28 -#endif
   12.29 +    lprintf("SPUDVB: rejected region %d = %dx%d\n", region_id, region_width, region_height );
   12.30      return;
   12.31    }
   12.32  
   12.33    if ( reg->width*reg->height<region_width*region_height ) {
   12.34 -#ifdef LOG
   12.35 -    printf("SPUDVB: update size of region %d = %dx%d\n", region_id, region_width, region_height);
   12.36 -#endif
   12.37 +    lprintf("SPUDVB: update size of region %d = %dx%d\n", region_id, region_width, region_height);
   12.38      if ( reg->img ) {
   12.39        free( reg->img );
   12.40        reg->img = NULL;
   12.41 @@ -177,9 +177,7 @@
   12.42    if ( fill ) {
   12.43      memset( reg->img, fill_color, region_width*region_height );
   12.44      reg->empty = 1;
   12.45 -#ifdef LOG
   12.46 -    printf("SPUDVB : FILL REGION %d\n", region_id);
   12.47 -#endif
   12.48 +    lprintf("SPUDVB: FILL REGION %d\n", region_id);
   12.49    }
   12.50    reg->width = region_width;
   12.51    reg->height = region_height;
   12.52 @@ -645,9 +643,7 @@
   12.53  	for ( i=0; i<MAX_REGIONS; i++ ) {
   12.54  	  if ( this->dvbsub->regions[i].osd ) {
   12.55  	    this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 );
   12.56 -#ifdef LOG
   12.57 -	    printf("SPUDVB: thread hiding = %d\n",i);
   12.58 -#endif
   12.59 +	    lprintf("SPUDVB: thread hiding = %d\n",i);
   12.60  	  }
   12.61  	}
   12.62        }
   12.63 @@ -700,7 +696,7 @@
   12.64  	  continue;
   12.65          /* clear osd */
   12.66          this->stream->osd_renderer->clear( this->dvbsub->regions[r].osd );
   12.67 -        if (this->dvbsub->regions[r].width>dest_width) {
   12.68 +        if ( this->dvbsub->regions[r].width>dest_width && !(this->stream->video_driver->get_capabilities(this->stream->video_driver) & VO_CAP_CUSTOM_EXTENT_OVERLAY)) {
   12.69  	  downscale_region_image(&this->dvbsub->regions[r], tmp, dest_width);
   12.70  	  reg = tmp;
   12.71  	  reg_width = dest_width;
   12.72 @@ -716,34 +712,25 @@
   12.73    }
   12.74  
   12.75    pthread_mutex_lock(&this->dvbsub_osd_mutex);
   12.76 -#ifdef LOG
   12.77 -  printf("SPUDVB: this->vpts=%llu\n",this->vpts);
   12.78 -#endif
   12.79 +  lprintf("SPUDVB: this->vpts=%llu\n",this->vpts);
   12.80    for ( r=0; r<MAX_REGIONS; r++ ) {
   12.81 -#ifdef LOG
   12.82 -    printf("SPUDVB : 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 );
   12.83 -#endif
   12.84 +    lprintf("SPUDVB: 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 );
   12.85      if ( this->dvbsub->page.regions[r].is_visible && this->dvbsub->regions[r].osd && !this->dvbsub->regions[r].empty ) {
   12.86 +      this->stream->osd_renderer->set_extent(this->dvbsub->regions[r].osd, SPU_MAX_WIDTH, SPU_MAX_HEIGHT);
   12.87        this->stream->osd_renderer->set_position( this->dvbsub->regions[r].osd, this->dvbsub->page.regions[r].x, this->dvbsub->page.regions[r].y );
   12.88        this->stream->osd_renderer->show( this->dvbsub->regions[r].osd, this->vpts );
   12.89 -#ifdef LOG
   12.90 -      printf("SPUDVB: show region = %d\n",r);
   12.91 -#endif
   12.92 +      lprintf("SPUDVB: show region = %d\n",r);
   12.93      }
   12.94      else {
   12.95        if ( this->dvbsub->regions[r].osd ) {
   12.96          this->stream->osd_renderer->hide( this->dvbsub->regions[r].osd, this->vpts );
   12.97 -#ifdef LOG
   12.98 -        printf("SPUDVB: hide region = %d\n",r);
   12.99 -#endif
  12.100 +        lprintf("SPUDVB: hide region = %d\n",r);
  12.101        }
  12.102      }
  12.103    }
  12.104    this->dvbsub_hide_timeout.tv_nsec = 0;
  12.105    this->dvbsub_hide_timeout.tv_sec = time(NULL) + this->dvbsub->page.page_time_out;
  12.106 -#ifdef LOG
  12.107 -  printf("SPUDVB: page_time_out %d\n",this->dvbsub->page.page_time_out);
  12.108 -#endif
  12.109 +  lprintf("SPUDVB: page_time_out %d\n",this->dvbsub->page.page_time_out);
  12.110    pthread_cond_signal(&this->dvbsub_restart_timeout);
  12.111    pthread_mutex_unlock(&this->dvbsub_osd_mutex);
  12.112  }
  12.113 @@ -807,9 +794,7 @@
  12.114      metronom_clock_t *clock = this->stream->xine->clock;
  12.115      int64_t curvpts = clock->get_current_time( clock );
  12.116      /* if buf->pts is unreliable, show page asap (better than nothing) */
  12.117 -#ifdef LOG
  12.118 -    printf("SPUDVB: spu_vpts=%lld - current_vpts=%lld\n", vpts, curvpts);
  12.119 -#endif
  12.120 +    lprintf("SPUDVB: spu_vpts=%lld - current_vpts=%lld\n", vpts, curvpts);
  12.121      if ( vpts<=curvpts || (vpts-curvpts)>(5*90000) )
  12.122        this->vpts = 0;
  12.123      else
    13.1 --- a/src/video_dec/Makefile.am	Thu Nov 19 15:29:17 2009 +0000
    13.2 +++ b/src/video_dec/Makefile.am	Fri Nov 20 03:46:10 2009 +0000
    13.3 @@ -1,6 +1,7 @@
    13.4  SUBDIRS = \
    13.5  	libmpeg2 \
    13.6 -	libmpeg2new
    13.7 +	libmpeg2new \
    13.8 +	libvdpau
    13.9  
   13.10  include $(top_builddir)/misc/Makefile.plugins
   13.11  include $(top_srcdir)/misc/Makefile.common
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/video_dec/libvdpau/Makefile.am	Fri Nov 20 03:46:10 2009 +0000
    14.3 @@ -0,0 +1,29 @@
    14.4 +include $(top_srcdir)/misc/Makefile.common
    14.5 +
    14.6 +AM_CFLAGS = $(DEFAULT_OCFLAGS) $(VISIBILITY_FLAG)
    14.7 +AM_LDFLAGS = $(xineplug_ldflags)
    14.8 +
    14.9 +noinst_HEADERS = bits_reader.h dpb.h h264_parser.h nal.h
   14.10 +
   14.11 +if ENABLE_VDPAU
   14.12 +vdpau_h264_module = xineplug_decode_vdpau_h264.la
   14.13 +VDPAU_CFLAGS = -D_ISOC99_SOURCE
   14.14 +
   14.15 +vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la
   14.16 +
   14.17 +vdpau_vc1_module = xineplug_decode_vdpau_vc1.la
   14.18 +endif
   14.19 +
   14.20 +xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) $(vdpau_vc1_module)
   14.21 +
   14.22 +xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c
   14.23 +xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS)
   14.24 +xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) -lm
   14.25 +
   14.26 +xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c
   14.27 +xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS)
   14.28 +xineplug_decode_vdpau_mpeg12_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS)
   14.29 +
   14.30 +xineplug_decode_vdpau_vc1_la_SOURCES = vdpau_vc1.c
   14.31 +xineplug_decode_vdpau_vc1_la_CFLAGS = $(AM_CFLAGS)
   14.32 +xineplug_decode_vdpau_vc1_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS)
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/video_dec/libvdpau/bits_reader.h	Fri Nov 20 03:46:10 2009 +0000
    15.3 @@ -0,0 +1,36 @@
    15.4 +#include <sys/types.h>
    15.5 +
    15.6 +
    15.7 +
    15.8 +typedef struct {
    15.9 +  uint8_t *buffer;
   15.10 +  int      offbits;
   15.11 +} bits_reader_t;
   15.12 +
   15.13 +static void bits_reader_set( bits_reader_t *br, uint8_t *buf )
   15.14 +{
   15.15 +  br->buffer = buf;
   15.16 +  br->offbits = 0;
   15.17 +}
   15.18 +
   15.19 +static uint32_t read_bits( bits_reader_t *br, int nbits )
   15.20 +{
   15.21 +  int i, nbytes;
   15.22 +  uint32_t ret = 0;
   15.23 +  uint8_t *buf;
   15.24 +
   15.25 +  buf = br->buffer;
   15.26 +  nbytes = (br->offbits + nbits)/8;
   15.27 +  if ( ((br->offbits + nbits) %8 ) > 0 )
   15.28 +    nbytes++;
   15.29 +  for ( i=0; i<nbytes; i++ )
   15.30 +    ret += buf[i]<<((nbytes-i-1)*8);
   15.31 +  i = (4-nbytes)*8+br->offbits;
   15.32 +  ret = ((ret<<i)>>i)>>((nbytes*8)-nbits-br->offbits);
   15.33 +
   15.34 +  br->offbits += nbits;
   15.35 +  br->buffer += br->offbits / 8;
   15.36 +  br->offbits %= 8;
   15.37 +
   15.38 +  return ret;
   15.39 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/video_dec/libvdpau/dpb.c	Fri Nov 20 03:46:10 2009 +0000
    16.3 @@ -0,0 +1,409 @@
    16.4 +/*
    16.5 + * Copyright (C) 2008 Julian Scheel
    16.6 + *
    16.7 + * This file is part of xine, a free video player.
    16.8 + *
    16.9 + * xine is free software; you can redistribute it and/or modify
   16.10 + * it under the terms of the GNU General Public License as published by
   16.11 + * the Free Software Foundation; either version 2 of the License, or
   16.12 + * (at your option) any later version.
   16.13 + *
   16.14 + * xine is distributed in the hope that it will be useful,
   16.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.17 + * GNU General Public License for more details.
   16.18 + *
   16.19 + * You should have received a copy of the GNU General Public License
   16.20 + * along with this program; if not, write to the Free Software
   16.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   16.22 + *
   16.23 + * dpb.c: Implementing Decoded Picture Buffer
   16.24 + */
   16.25 +
   16.26 +#include <stdio.h>
   16.27 +#include <stdlib.h>
   16.28 +#include <string.h>
   16.29 +
   16.30 +#include "dpb.h"
   16.31 +#include "nal.h"
   16.32 +#include <xine/video_out.h>
   16.33 +
   16.34 +struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal,
   16.35 +    VdpVideoSurface surface, vo_frame_t *img)
   16.36 +{
   16.37 +  struct decoded_picture *pic = calloc(1, sizeof(struct decoded_picture));
   16.38 +  pic->nal = init_nal_unit();
   16.39 +  copy_nal_unit(pic->nal, src_nal);
   16.40 +  pic->top_is_reference = pic->nal->slc->field_pic_flag
   16.41 +        ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1;
   16.42 +  pic->bottom_is_reference = pic->nal->slc->field_pic_flag
   16.43 +        ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1;
   16.44 +  pic->surface = surface;
   16.45 +  pic->img = img;
   16.46 +
   16.47 +  return pic;
   16.48 +}
   16.49 +
   16.50 +void free_decoded_picture(struct decoded_picture *pic)
   16.51 +{
   16.52 +  pic->img->free(pic->img);
   16.53 +  free_nal_unit(pic->nal);
   16.54 +  free(pic);
   16.55 +}
   16.56 +
   16.57 +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush)
   16.58 +{
   16.59 +  struct decoded_picture *pic = dpb->pictures;
   16.60 +  struct decoded_picture *outpic = NULL;
   16.61 +
   16.62 +  if(!do_flush && dpb->used < MAX_DPB_SIZE)
   16.63 +    return NULL;
   16.64 +
   16.65 +  if (pic != NULL)
   16.66 +    do {
   16.67 +      if (pic->delayed_output &&
   16.68 +          (outpic == NULL ||
   16.69 +              (pic->nal->top_field_order_cnt <= outpic->nal->top_field_order_cnt &&
   16.70 +                  pic->nal->bottom_field_order_cnt <= outpic->nal->bottom_field_order_cnt)||
   16.71 +              (outpic->nal->top_field_order_cnt < 0 && pic->nal->top_field_order_cnt > 0 &&
   16.72 +                  outpic->nal->bottom_field_order_cnt < 0 && pic->nal->bottom_field_order_cnt > 0)||
   16.73 +              outpic->nal->nal_unit_type == NAL_SLICE_IDR))
   16.74 +        outpic = pic;
   16.75 +    } while ((pic = pic->next) != NULL);
   16.76 +
   16.77 +  return outpic;
   16.78 +}
   16.79 +
   16.80 +struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum)
   16.81 +{
   16.82 +  struct decoded_picture *pic = dpb->pictures;
   16.83 +
   16.84 +  if (pic != NULL)
   16.85 +    do {
   16.86 +      if (pic->nal->curr_pic_num == picnum)
   16.87 +        return pic;
   16.88 +    } while ((pic = pic->next) != NULL);
   16.89 +
   16.90 +  return NULL;
   16.91 +}
   16.92 +
   16.93 +struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb,
   16.94 +    uint32_t longterm_picnum)
   16.95 +{
   16.96 +  struct decoded_picture *pic = dpb->pictures;
   16.97 +
   16.98 +  if (pic != NULL)
   16.99 +    do {
  16.100 +      if (pic->nal->long_term_pic_num == longterm_picnum)
  16.101 +        return pic;
  16.102 +    } while ((pic = pic->next) != NULL);
  16.103 +
  16.104 +  return NULL;
  16.105 +}
  16.106 +
  16.107 +struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb,
  16.108 +    uint32_t longterm_idx)
  16.109 +{
  16.110 +  struct decoded_picture *pic = dpb->pictures;
  16.111 +
  16.112 +  if (pic != NULL)
  16.113 +    do {
  16.114 +      if (pic->nal->long_term_frame_idx == longterm_idx)
  16.115 +        return pic;
  16.116 +    } while ((pic = pic->next) != NULL);
  16.117 +
  16.118 +  return NULL;
  16.119 +}
  16.120 +
  16.121 +int dpb_set_unused_ref_picture_a(struct dpb *dpb, struct decoded_picture *refpic)
  16.122 +{
  16.123 +  struct decoded_picture *pic = dpb->pictures;
  16.124 +    if (pic != NULL)
  16.125 +      do {
  16.126 +        if (pic == refpic) {
  16.127 +          pic->used_for_reference = 0;
  16.128 +          if(!pic->delayed_output)
  16.129 +            dpb_remove_picture(dpb, pic);
  16.130 +          return 0;
  16.131 +        }
  16.132 +      } while ((pic = pic->next) != NULL);
  16.133 +
  16.134 +    return -1;
  16.135 +}
  16.136 +
  16.137 +int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum)
  16.138 +{
  16.139 +  struct decoded_picture *pic = dpb->pictures;
  16.140 +  if (pic != NULL)
  16.141 +    do {
  16.142 +      if (pic->nal->curr_pic_num == picnum) {
  16.143 +        pic->used_for_reference = 0;
  16.144 +        if(!pic->delayed_output)
  16.145 +          dpb_remove_picture(dpb, pic);
  16.146 +        return 0;
  16.147 +      }
  16.148 +    } while ((pic = pic->next) != NULL);
  16.149 +
  16.150 +  return -1;
  16.151 +}
  16.152 +
  16.153 +int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum)
  16.154 +{
  16.155 +  struct decoded_picture *pic = dpb->pictures;
  16.156 +  if (pic != NULL)
  16.157 +    do {
  16.158 +      if (pic->nal->long_term_pic_num == longterm_picnum) {
  16.159 +        pic->used_for_reference = 0;
  16.160 +        if(!pic->delayed_output)
  16.161 +          dpb_remove_picture(dpb, pic);
  16.162 +        return 0;
  16.163 +      }
  16.164 +    } while ((pic = pic->next) != NULL);
  16.165 +
  16.166 +  return -1;
  16.167 +}
  16.168 +
  16.169 +int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx)
  16.170 +{
  16.171 +  struct decoded_picture *pic = dpb->pictures;
  16.172 +  if (pic != NULL)
  16.173 +    do {
  16.174 +      if (pic->nal->long_term_frame_idx == longterm_idx) {
  16.175 +        pic->nal->used_for_long_term_ref = 0;
  16.176 +        pic->used_for_reference = 0;
  16.177 +        if(!pic->delayed_output)
  16.178 +          dpb_remove_picture(dpb, pic);
  16.179 +        return 0;
  16.180 +      }
  16.181 +    } while ((pic = pic->next) != NULL);
  16.182 +
  16.183 +  return -1;
  16.184 +}
  16.185 +
  16.186 +int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx)
  16.187 +{
  16.188 +  struct decoded_picture *pic = dpb->pictures;
  16.189 +  if (pic != NULL)
  16.190 +    do {
  16.191 +      if (pic->nal->long_term_frame_idx >= longterm_idx) {
  16.192 +        pic->used_for_reference = 0;
  16.193 +        if(!pic->delayed_output) {
  16.194 +          struct decoded_picture *next_pic = pic->next;
  16.195 +          dpb_remove_picture(dpb, pic);
  16.196 +          pic = next_pic;
  16.197 +          continue;
  16.198 +        }
  16.199 +      }
  16.200 +    } while ((pic = pic->next) != NULL);
  16.201 +
  16.202 +  return -1;
  16.203 +}
  16.204 +
  16.205 +
  16.206 +int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic)
  16.207 +{
  16.208 +  struct decoded_picture *pic = dpb->pictures;
  16.209 +  if (pic != NULL)
  16.210 +    do {
  16.211 +      if (pic == outpic) {
  16.212 +        pic->delayed_output = 0;
  16.213 +        if(!pic->used_for_reference)
  16.214 +          dpb_remove_picture(dpb, pic);
  16.215 +        return 0;
  16.216 +      }
  16.217 +    } while ((pic = pic->next) != NULL);
  16.218 +
  16.219 +  return -1;
  16.220 +}
  16.221 +
  16.222 +int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic)
  16.223 +{
  16.224 +  struct decoded_picture *pic = dpb->pictures;
  16.225 +  struct decoded_picture *last_pic = NULL;
  16.226 +
  16.227 +  if (pic != NULL)
  16.228 +    do {
  16.229 +      if (pic == rempic) {
  16.230 +        // FIXME: free the picture....
  16.231 +
  16.232 +        if (last_pic != NULL)
  16.233 +          last_pic->next = pic->next;
  16.234 +        else
  16.235 +          dpb->pictures = pic->next;
  16.236 +        free_decoded_picture(pic);
  16.237 +        dpb->used--;
  16.238 +        return 0;
  16.239 +      }
  16.240 +
  16.241 +      last_pic = pic;
  16.242 +    } while ((pic = pic->next) != NULL);
  16.243 +
  16.244 +  return -1;
  16.245 +}
  16.246 +
  16.247 +static int dpb_remove_picture_by_img(struct dpb *dpb, vo_frame_t *remimg)
  16.248 +{
  16.249 +  struct decoded_picture *pic = dpb->pictures;
  16.250 +  struct decoded_picture *last_pic = NULL;
  16.251 +
  16.252 +  if (pic != NULL)
  16.253 +    do {
  16.254 +      if (pic->img == remimg) {
  16.255 +        // FIXME: free the picture....
  16.256 +
  16.257 +        if (last_pic != NULL)
  16.258 +          last_pic->next = pic->next;
  16.259 +        else
  16.260 +          dpb->pictures = pic->next;
  16.261 +        free_decoded_picture(pic);
  16.262 +        dpb->used--;
  16.263 +        return 0;
  16.264 +      }
  16.265 +
  16.266 +      last_pic = pic;
  16.267 +    } while ((pic = pic->next) != NULL);
  16.268 +
  16.269 +  return -1;
  16.270 +}
  16.271 +
  16.272 +int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum)
  16.273 +{
  16.274 +  struct decoded_picture *pic = dpb->pictures;
  16.275 +  struct decoded_picture *last_pic = NULL;
  16.276 +
  16.277 +  if (pic != NULL)
  16.278 +    do {
  16.279 +      if (pic->nal->curr_pic_num == picnum) {
  16.280 +        dpb_remove_picture(dpb, pic);
  16.281 +      }
  16.282 +
  16.283 +      last_pic = pic;
  16.284 +    } while ((pic = pic->next) != NULL);
  16.285 +
  16.286 +  return -1;
  16.287 +}
  16.288 +
  16.289 +int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames)
  16.290 +{
  16.291 +  pic->img->lock(pic->img);
  16.292 +  if (0 == dpb_remove_picture_by_img(dpb, pic->img))
  16.293 +    fprintf(stderr, "broken stream: current img was already in dpb -- freed it\n");
  16.294 +  else
  16.295 +    pic->img->free(pic->img);
  16.296 +
  16.297 +  int i = 0;
  16.298 +  struct decoded_picture *last_pic = dpb->pictures;
  16.299 +
  16.300 +  pic->next = dpb->pictures;
  16.301 +  dpb->pictures = pic;
  16.302 +  dpb->num_ref_frames = num_ref_frames;
  16.303 +  dpb->used++;
  16.304 +
  16.305 +  if(pic != NULL && dpb->used > num_ref_frames) {
  16.306 +    do {
  16.307 +      if(pic->used_for_reference) {
  16.308 +        i++;
  16.309 +        if(i>num_ref_frames) {
  16.310 +          pic->used_for_reference = 0;
  16.311 +          if(pic == dpb->pictures)
  16.312 +            last_pic = pic->next;
  16.313 +
  16.314 +          if(!pic->delayed_output) {
  16.315 +            dpb_remove_picture(dpb, pic);
  16.316 +          }
  16.317 +          pic = last_pic;
  16.318 +          if(pic == dpb->pictures)
  16.319 +            continue;
  16.320 +        }
  16.321 +        last_pic = pic;
  16.322 +      }
  16.323 +    } while (pic != NULL && (pic = pic->next) != NULL);
  16.324 +  }
  16.325 +
  16.326 +  return 0;
  16.327 +}
  16.328 +
  16.329 +int dpb_flush(struct dpb *dpb)
  16.330 +{
  16.331 +  struct decoded_picture *pic = dpb->pictures;
  16.332 +
  16.333 +  if (pic != NULL)
  16.334 +    do {
  16.335 +      struct decoded_picture *next_pic = pic->next;
  16.336 +      dpb_set_unused_ref_picture_a(dpb, pic);
  16.337 +      pic = next_pic;
  16.338 +    } while (pic != NULL);
  16.339 +
  16.340 +  //printf("Flushed, used: %d\n", dpb->used);
  16.341 +
  16.342 +  return 0;
  16.343 +}
  16.344 +
  16.345 +void dpb_free_all( struct dpb *dpb )
  16.346 +{
  16.347 +  struct decoded_picture *pic = dpb->pictures;
  16.348 +
  16.349 +  if (pic != NULL)
  16.350 +    do {
  16.351 +      struct decoded_picture *next_pic = pic->next;
  16.352 +      free_decoded_picture(pic);
  16.353 +      --dpb->used;
  16.354 +      pic = next_pic;
  16.355 +    } while (pic != NULL);
  16.356 +
  16.357 +  printf("dpb_free_all, used: %d\n", dpb->used);
  16.358 +  dpb->pictures = NULL;
  16.359 +}
  16.360 +
  16.361 +void dpb_clear_all_pts( struct dpb *dpb )
  16.362 +{
  16.363 +  struct decoded_picture *pic = dpb->pictures;
  16.364 +
  16.365 +  while (pic != NULL) {
  16.366 +    pic->img->pts = 0;
  16.367 +    pic = pic->next;
  16.368 +  }
  16.369 +}
  16.370 +
  16.371 +int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist)
  16.372 +{
  16.373 +  struct decoded_picture *pic = dpb->pictures;
  16.374 +  struct decoded_picture *last_pic = NULL;
  16.375 +
  16.376 +  int i = 0;
  16.377 +  int used_refframes = 0;
  16.378 +
  16.379 +  if (pic != NULL)
  16.380 +    do {
  16.381 +      if (pic->used_for_reference) {
  16.382 +        reflist[i].surface = pic->surface;
  16.383 +        reflist[i].is_long_term = pic->nal->used_for_long_term_ref;
  16.384 +        if(reflist[i].is_long_term)
  16.385 +          reflist[i].frame_idx = pic->nal->slc->frame_num;
  16.386 +        else
  16.387 +          reflist[i].frame_idx = pic->nal->slc->frame_num;
  16.388 +        reflist[i].top_is_reference = pic->top_is_reference;
  16.389 +        reflist[i].bottom_is_reference = pic->bottom_is_reference;
  16.390 +        reflist[i].field_order_cnt[0] = pic->nal->top_field_order_cnt;
  16.391 +        reflist[i].field_order_cnt[1] = pic->nal->bottom_field_order_cnt;
  16.392 +        i++;
  16.393 +      }
  16.394 +      last_pic = pic;
  16.395 +    } while ((pic = pic->next) != NULL && i < 16);
  16.396 +
  16.397 +  used_refframes = i;
  16.398 +
  16.399 +  // fill all other frames with invalid handles
  16.400 +  while(i < 16) {
  16.401 +    reflist[i].bottom_is_reference = VDP_FALSE;
  16.402 +    reflist[i].top_is_reference = VDP_FALSE;
  16.403 +    reflist[i].frame_idx = 0;
  16.404 +    reflist[i].is_long_term = VDP_FALSE;
  16.405 +    reflist[i].surface = VDP_INVALID_HANDLE;
  16.406 +    reflist[i].field_order_cnt[0] = 0;
  16.407 +    reflist[i].field_order_cnt[1] = 0;
  16.408 +    i++;
  16.409 +  }
  16.410 +
  16.411 +  return used_refframes;
  16.412 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/video_dec/libvdpau/dpb.h	Fri Nov 20 03:46:10 2009 +0000
    17.3 @@ -0,0 +1,80 @@
    17.4 +/*
    17.5 + * Copyright (C) 2008 Julian Scheel
    17.6 + *
    17.7 + * This file is part of xine, a free video player.
    17.8 + *
    17.9 + * xine is free software; you can redistribute it and/or modify
   17.10 + * it under the terms of the GNU General Public License as published by
   17.11 + * the Free Software Foundation; either version 2 of the License, or
   17.12 + * (at your option) any later version.
   17.13 + *
   17.14 + * xine is distributed in the hope that it will be useful,
   17.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.17 + * GNU General Public License for more details.
   17.18 + *
   17.19 + * You should have received a copy of the GNU General Public License
   17.20 + * along with this program; if not, write to the Free Software
   17.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   17.22 + *
   17.23 + * dpb.h: Decoder Picture Buffer
   17.24 + */
   17.25 +
   17.26 +#ifndef DPB_H_
   17.27 +#define DPB_H_
   17.28 +
   17.29 +#define MAX_DPB_SIZE 16
   17.30 +
   17.31 +#include "nal.h"
   17.32 +#include <xine/video_out.h>
   17.33 +
   17.34 +struct decoded_picture {
   17.35 +  VdpVideoSurface surface;
   17.36 +  vo_frame_t *img; /* this is the image we block, to make sure
   17.37 +                    * the surface is not double-used */
   17.38 +  struct nal_unit *nal;
   17.39 +
   17.40 +  uint8_t used_for_reference;
   17.41 +  uint8_t top_is_reference;
   17.42 +  uint8_t bottom_is_reference;
   17.43 +
   17.44 +  uint8_t delayed_output;
   17.45 +
   17.46 +  struct decoded_picture *next;
   17.47 +};
   17.48 +
   17.49 +/* Decoded Picture Buffer */
   17.50 +struct dpb {
   17.51 +  struct decoded_picture *pictures;
   17.52 +
   17.53 +  uint32_t num_ref_frames;
   17.54 +  uint32_t used;
   17.55 +};
   17.56 +
   17.57 +struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal,
   17.58 +    VdpVideoSurface surface, vo_frame_t *img);
   17.59 +void free_decoded_picture(struct decoded_picture *pic);
   17.60 +
   17.61 +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush);
   17.62 +
   17.63 +struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum);
   17.64 +struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum);
   17.65 +struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx);
   17.66 +
   17.67 +int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum);
   17.68 +int dpb_set_unused_ref_picture_a(struct dpb *dpb, struct decoded_picture *refpic);
   17.69 +int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum);
   17.70 +int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx);
   17.71 +int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx);
   17.72 +
   17.73 +int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic);
   17.74 +
   17.75 +int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic);
   17.76 +int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames);
   17.77 +int dpb_flush(struct dpb *dpb);
   17.78 +void dpb_free_all( struct dpb *dpb );
   17.79 +void dpb_clear_all_pts( struct dpb *dpb );
   17.80 +
   17.81 +int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist);
   17.82 +
   17.83 +#endif /* DPB_H_ */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/video_dec/libvdpau/h264_parser.c	Fri Nov 20 03:46:10 2009 +0000
    18.3 @@ -0,0 +1,1594 @@
    18.4 +/*
    18.5 + * Copyright (C) 2008 Julian Scheel
    18.6 + *
    18.7 + * This file is part of xine, a free video player.
    18.8 + *
    18.9 + * xine is free software; you can redistribute it and/or modify
   18.10 + * it under the terms of the GNU General Public License as published by
   18.11 + * the Free Software Foundation; either version 2 of the License, or
   18.12 + * (at your option) any later version.
   18.13 + *
   18.14 + * xine is distributed in the hope that it will be useful,
   18.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.17 + * GNU General Public License for more details.
   18.18 + *
   18.19 + * You should have received a copy of the GNU General Public License
   18.20 + * along with this program; if not, write to the Free Software
   18.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   18.22 + *
   18.23 + * h264_parser.c: Almost full-features H264 NAL-Parser
   18.24 + */
   18.25 +
   18.26 +#include <stdio.h>
   18.27 +#include <stdlib.h>
   18.28 +#include <math.h>
   18.29 +
   18.30 +#include "h264_parser.h"
   18.31 +#include "nal.h"
   18.32 +
   18.33 +/* default scaling_lists according to Table 7-2 */
   18.34 +uint8_t default_4x4_intra[16] = { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32,
   18.35 +    32, 32, 37, 37, 42 };
   18.36 +
   18.37 +uint8_t default_4x4_inter[16] = { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27,
   18.38 +    27, 27, 30, 30, 34 };
   18.39 +
   18.40 +uint8_t default_8x8_intra[64] = { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18,
   18.41 +    18, 18, 18, 18, 23, 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27,
   18.42 +    27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31,
   18.43 +    33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 };
   18.44 +
   18.45 +uint8_t default_8x8_inter[64] = { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19,
   18.46 +    19, 19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24,
   18.47 +    24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27,
   18.48 +    28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 };
   18.49 +
   18.50 +struct buf_reader
   18.51 +{
   18.52 +  uint8_t *buf;
   18.53 +  uint8_t *cur_pos;
   18.54 +  int len;
   18.55 +  int cur_offset;
   18.56 +};
   18.57 +
   18.58 +static inline uint32_t read_bits(struct buf_reader *buf, int len);
   18.59 +uint32_t read_exp_golomb(struct buf_reader *buf);
   18.60 +int32_t read_exp_golomb_s(struct buf_reader *buf);
   18.61 +
   18.62 +void calculate_pic_order(struct nal_parser *parser);
   18.63 +void skip_scaling_list(struct buf_reader *buf, int size);
   18.64 +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list,
   18.65 +    int length, int index);
   18.66 +int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser);
   18.67 +static void sps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, int i);
   18.68 +static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct pic_parameter_set_rbsp *pps, int i);
   18.69 +uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser);
   18.70 +void parse_vui_parameters(struct buf_reader *buf,
   18.71 +    struct seq_parameter_set_rbsp *sps);
   18.72 +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd);
   18.73 +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps,
   18.74 +    struct seq_parameter_set_rbsp *sps);
   18.75 +void parse_sei(struct buf_reader *buf, struct nal_parser *parser);
   18.76 +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser);
   18.77 +void
   18.78 +    parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal,
   18.79 +        struct nal_parser *parser);
   18.80 +void decode_ref_pic_marking(struct nal_unit *nal,
   18.81 +    uint32_t memory_management_control_operation,
   18.82 +    uint32_t marking_nr,
   18.83 +    struct nal_parser *parser);
   18.84 +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal);
   18.85 +void parse_dec_ref_pic_marking(struct buf_reader *buf,
   18.86 +    struct nal_parser *parser);
   18.87 +
   18.88 +/* here goes the parser implementation */
   18.89 +
   18.90 +static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len)
   18.91 +{
   18.92 +  uint8_t *end = &buf[buf_len];
   18.93 +  uint8_t *pos = malloc(buf_len);
   18.94 +
   18.95 +  *ret = pos;
   18.96 +  while (buf < end) {
   18.97 +    if (buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x03) {
   18.98 +
   18.99 +      *pos++ = 0x00;
  18.100 +      *pos++ = 0x00;
  18.101 +
  18.102 +      buf += 3;
  18.103 +      continue;
  18.104 +    }
  18.105 +    *pos++ = *buf++;
  18.106 +  }
  18.107 +
  18.108 +  *len_ret = pos - *ret;
  18.109 +}
  18.110 +
  18.111 +#if 0
  18.112 +static inline void dump_bits(const char *label, const struct buf_reader *buf, int bits)
  18.113 +{
  18.114 +  struct buf_reader lbuf;
  18.115 +  memcpy(&lbuf, buf, sizeof(struct buf_reader));
  18.116 +
  18.117 +  int i;
  18.118 +  printf("%s: 0b", label);
  18.119 +  for(i=0; i < bits; i++)
  18.120 +    printf("%d", read_bits(&lbuf, 1));
  18.121 +  printf("\n");
  18.122 +}
  18.123 +#endif
  18.124 +
  18.125 +static inline uint32_t bits_read(struct buf_reader *buf)
  18.126 +{
  18.127 +  int bits_read = 0;
  18.128 +  bits_read = (buf->cur_pos - buf->buf)*8;
  18.129 +  bits_read += (8-buf->cur_offset);
  18.130 +
  18.131 +  return bits_read;
  18.132 +}
  18.133 +
  18.134 +static inline uint32_t read_bits(struct buf_reader *buf, int len)
  18.135 +{
  18.136 +  static uint32_t i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f,
  18.137 +      0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff,
  18.138 +      0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
  18.139 +      0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff,
  18.140 +      0x3fffffff, 0x7fffffff, 0xffffffff };
  18.141 +
  18.142 +  int i_shr;
  18.143 +  uint32_t bits = 0;
  18.144 +
  18.145 +  while (len > 0 && (buf->cur_pos - buf->buf) < buf->len) {
  18.146 +    if ((i_shr = buf->cur_offset - len) >= 0) {
  18.147 +      bits |= (*buf->cur_pos >> i_shr) & i_mask[len];
  18.148 +      buf->cur_offset -= len;
  18.149 +      if (buf->cur_offset == 0) {
  18.150 +        buf->cur_pos++;
  18.151 +        buf->cur_offset = 8;
  18.152 +      }
  18.153 +      return bits;
  18.154 +    }
  18.155 +    else {
  18.156 +      bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr;
  18.157 +      len -= buf->cur_offset;
  18.158 +      buf->cur_pos++;
  18.159 +      buf->cur_offset = 8;
  18.160 +    }
  18.161 +  }
  18.162 +  return bits;
  18.163 +}
  18.164 +
  18.165 +/* determines if following bits are rtsb_trailing_bits */
  18.166 +static inline int rbsp_trailing_bits(uint8_t *buf, int buf_len)
  18.167 +{
  18.168 +  uint8_t *cur_buf = buf+(buf_len-1);
  18.169 +  uint8_t cur_val;
  18.170 +  int parsed_bits = 0;
  18.171 +  int i;
  18.172 +
  18.173 +  while(buf_len > 0) {
  18.174 +    cur_val = *cur_buf;
  18.175 +    for(i = 0; i < 9; i++) {
  18.176 +      if (cur_val&1)
  18.177 +        return parsed_bits+i;
  18.178 +      cur_val>>=1;
  18.179 +    }
  18.180 +    parsed_bits += 8;
  18.181 +    cur_buf--;
  18.182 +  }
  18.183 +
  18.184 +  printf("rbsp trailing bits could not be found\n");
  18.185 +  return 0;
  18.186 +}
  18.187 +
  18.188 +uint32_t read_exp_golomb(struct buf_reader *buf)
  18.189 +{
  18.190 +  int leading_zero_bits = 0;
  18.191 +
  18.192 +  while (read_bits(buf, 1) == 0 && leading_zero_bits < 32)
  18.193 +    leading_zero_bits++;
  18.194 +
  18.195 +  uint32_t code = (1 << leading_zero_bits) - 1 + read_bits(buf,
  18.196 +      leading_zero_bits);
  18.197 +  return code;
  18.198 +}
  18.199 +
  18.200 +int32_t read_exp_golomb_s(struct buf_reader *buf)
  18.201 +{
  18.202 +  uint32_t ue = read_exp_golomb(buf);
  18.203 +  int32_t code = ue & 0x01 ? (ue + 1) / 2 : -(ue / 2);
  18.204 +  return code;
  18.205 +}
  18.206 +
  18.207 +int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser)
  18.208 +{
  18.209 +  if (buf->len < 1)
  18.210 +    return -1;
  18.211 +
  18.212 +  int ret = -1;
  18.213 +
  18.214 +  struct nal_unit *nal = parser->current_nal;
  18.215 +
  18.216 +  memset(nal, 0x00, sizeof(struct nal_unit) - sizeof(struct seq_parameter_set_rbsp*) - sizeof(struct pic_parameter_set_rbsp*) - sizeof(struct slice_header*));
  18.217 +  nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03;
  18.218 +  nal->nal_unit_type = buf->buf[0] & 0x1f;
  18.219 +
  18.220 +  buf->cur_pos = buf->buf + 1;
  18.221 +  //printf("NAL: %d\n", nal->nal_unit_type);
  18.222 +
  18.223 +  struct buf_reader ibuf;
  18.224 +  ibuf.cur_offset = 8;
  18.225 +
  18.226 +  switch (nal->nal_unit_type) {
  18.227 +    case NAL_SPS:
  18.228 +      decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len - 1);
  18.229 +      ibuf.cur_pos = ibuf.buf;
  18.230 +
  18.231 +      if (!nal->sps)
  18.232 +        nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp));
  18.233 +      else
  18.234 +        memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp));
  18.235 +
  18.236 +      parse_sps(&ibuf, parser);
  18.237 +      free(ibuf.buf);
  18.238 +      ret = NAL_SPS;
  18.239 +      break;
  18.240 +    case NAL_PPS:
  18.241 +      if (!nal->pps)
  18.242 +        nal->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp));
  18.243 +      else
  18.244 +        memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp));
  18.245 +
  18.246 +      parse_pps(buf, nal->pps, nal->sps);
  18.247 +      ret = NAL_PPS;
  18.248 +      break;
  18.249 +    case NAL_SLICE:
  18.250 +    case NAL_PART_A:
  18.251 +    case NAL_PART_B:
  18.252 +    case NAL_PART_C:
  18.253 +    case NAL_SLICE_IDR:
  18.254 +      if (nal->sps && nal->pps) {
  18.255 +        if (!nal->slc)
  18.256 +          nal->slc = calloc(1, sizeof(struct slice_header));
  18.257 +        else
  18.258 +          memset(nal->slc, 0x00, sizeof(struct slice_header));
  18.259 +
  18.260 +        parse_slice_header(buf, parser);
  18.261 +        ret = nal->nal_unit_type;
  18.262 +      }
  18.263 +      break;
  18.264 +    case NAL_SEI:
  18.265 +      memset(&(nal->sei), 0x00, sizeof(struct sei_message));
  18.266 +      parse_sei(buf, parser);
  18.267 +      ret = nal->nal_unit_type;
  18.268 +      break;
  18.269 +    default:
  18.270 +      ret = nal->nal_unit_type;
  18.271 +      break;
  18.272 +  }
  18.273 +
  18.274 +  return ret;
  18.275 +}
  18.276 +
  18.277 +void calculate_pic_order(struct nal_parser *parser)
  18.278 +{
  18.279 +  struct nal_unit *nal = parser->current_nal;
  18.280 +
  18.281 +  struct seq_parameter_set_rbsp *sps = nal->sps;
  18.282 +  struct slice_header *slc = nal->slc;
  18.283 +  if (!sps || !slc)
  18.284 +    return;
  18.285 +
  18.286 +  if (nal->nal_unit_type == NAL_SLICE_IDR) {
  18.287 +    parser->prev_pic_order_cnt_lsb = 0;
  18.288 +    parser->prev_pic_order_cnt_msb = 0;
  18.289 +    parser->frame_num_offset = 0;
  18.290 +  }
  18.291 +
  18.292 +  if (sps->pic_order_cnt_type == 0) {
  18.293 +
  18.294 +    const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
  18.295 +
  18.296 +    if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb
  18.297 +        && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb
  18.298 +            >= max_poc_lsb / 2)
  18.299 +      parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + max_poc_lsb;
  18.300 +    else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb
  18.301 +        && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb
  18.302 +            < -max_poc_lsb / 2)
  18.303 +      parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - max_poc_lsb;
  18.304 +    else
  18.305 +      parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb;
  18.306 +
  18.307 +    if(!slc->field_pic_flag || !slc->bottom_field_flag)
  18.308 +      nal->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb;
  18.309 +
  18.310 +    nal->bottom_field_order_cnt = 0;
  18.311 +
  18.312 +    if(!slc->field_pic_flag)
  18.313 +      nal->bottom_field_order_cnt = nal->top_field_order_cnt + slc->delta_pic_order_cnt_bottom;
  18.314 +    else //if(slc->bottom_field_flag) TODO: this is not spec compliant, but works...
  18.315 +      nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb;
  18.316 +
  18.317 +    /*if(slc->bottom_field_flag)
  18.318 +      nal->top_field_order_cnt = parser->last_nal->top_field_order_cnt;*/
  18.319 +
  18.320 +  } else if (sps->pic_order_cnt_type == 2) {
  18.321 +    uint32_t prev_frame_num = parser->last_nal->slc->frame_num;
  18.322 +    uint32_t prev_frame_num_offset = parser->frame_num_offset;
  18.323 +    uint32_t max_frame_num = 1 << (sps->log2_max_frame_num_minus4+4);
  18.324 +    uint32_t temp_pic_order_cnt = 0;
  18.325 +
  18.326 +    if (parser->is_idr)
  18.327 +      parser->frame_num_offset = 0;
  18.328 +    else if (prev_frame_num > slc->frame_num)
  18.329 +      parser->frame_num_offset = prev_frame_num_offset + max_frame_num;
  18.330 +    else
  18.331 +      parser->frame_num_offset = prev_frame_num_offset;
  18.332 +
  18.333 +    if(parser->is_idr)
  18.334 +      temp_pic_order_cnt = 0;
  18.335 +    else if(nal->nal_ref_idc == 0)
  18.336 +      temp_pic_order_cnt = 2 * (parser->frame_num_offset + slc->frame_num)-1;
  18.337 +    else
  18.338 +      temp_pic_order_cnt = 2 * (parser->frame_num_offset + slc->frame_num);
  18.339 +
  18.340 +    if(!slc->field_pic_flag)
  18.341 +      nal->top_field_order_cnt = nal->bottom_field_order_cnt = temp_pic_order_cnt;
  18.342 +    else if(slc->bottom_field_flag)
  18.343 +      nal->bottom_field_order_cnt = temp_pic_order_cnt;
  18.344 +    else
  18.345 +      nal->top_field_order_cnt = temp_pic_order_cnt;
  18.346 +
  18.347 +  } else {
  18.348 +    printf("FIXME: Unsupported poc_type: %d\n", sps->pic_order_cnt_type);
  18.349 +  }
  18.350 +
  18.351 +}
  18.352 +
  18.353 +void skip_scaling_list(struct buf_reader *buf, int size)
  18.354 +{
  18.355 +  int i;
  18.356 +  for (i = 0; i < size; i++) {
  18.357 +    read_exp_golomb_s(buf);
  18.358 +  }
  18.359 +}
  18.360 +
  18.361 +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list,
  18.362 +    int length, int index)
  18.363 +{
  18.364 +  int last_scale = 8;
  18.365 +  int next_scale = 8;
  18.366 +  int32_t delta_scale;
  18.367 +  uint8_t use_default_scaling_matrix_flag = 0;
  18.368 +  int i;
  18.369 +
  18.370 +  uint8_t *zigzag = (length==64) ? zigzag_8x8 : zigzag_4x4;
  18.371 +
  18.372 +  for (i = 0; i < length; i++) {
  18.373 +    if (next_scale != 0) {
  18.374 +      delta_scale = read_exp_golomb_s(buf);
  18.375 +      next_scale = (last_scale + delta_scale + 256) % 256;
  18.376 +      if (i == 0 && next_scale == 0) {
  18.377 +        use_default_scaling_matrix_flag = 1;
  18.378 +        break;
  18.379 +      }
  18.380 +    }
  18.381 +    scaling_list[zigzag[i]] = last_scale = (next_scale == 0) ? last_scale : next_scale;
  18.382 +  }
  18.383 +
  18.384 +  if (use_default_scaling_matrix_flag) {
  18.385 +    switch (index) {
  18.386 +      case 0:
  18.387 +      case 1:
  18.388 +      case 2: {
  18.389 +        for(i = 0; i < sizeof(default_4x4_intra); i++) {
  18.390 +          scaling_list[zigzag_4x4[i]] = default_4x4_intra[i];
  18.391 +        }
  18.392 +        //memcpy(scaling_list, default_4x4_intra, sizeof(default_4x4_intra));
  18.393 +        break;
  18.394 +      }
  18.395 +      case 3:
  18.396 +      case 4:
  18.397 +      case 5: {
  18.398 +        for(i = 0; i < sizeof(default_4x4_inter); i++) {
  18.399 +          scaling_list[zigzag_4x4[i]] = default_4x4_inter[i];
  18.400 +        }
  18.401 +        //memcpy(scaling_list, default_4x4_inter, sizeof(default_4x4_inter));
  18.402 +        break;
  18.403 +      }
  18.404 +      case 6: {
  18.405 +        for(i = 0; i < sizeof(default_8x8_intra); i++) {
  18.406 +          scaling_list[zigzag_8x8[i]] = default_8x8_intra[i];
  18.407 +        }
  18.408 +        //memcpy(scaling_list, default_8x8_intra, sizeof(default_8x8_intra));
  18.409 +        break;
  18.410 +      }
  18.411 +      case 7: {
  18.412 +        for(i = 0; i < sizeof(default_8x8_inter); i++) {
  18.413 +          scaling_list[zigzag_8x8[i]] = default_8x8_inter[i];
  18.414 +        }
  18.415 +        //memcpy(scaling_list, default_8x8_inter, sizeof(default_8x8_inter));
  18.416 +        break;
  18.417 +      }
  18.418 +    }
  18.419 +  }
  18.420 +}
  18.421 +
  18.422 +static void sps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, int i)
  18.423 +{
  18.424 +  int j;
  18.425 +  switch (i) {
  18.426 +    case 0: {
  18.427 +      for(j = 0; j < sizeof(default_4x4_intra); j++) {
  18.428 +        sps->scaling_lists_4x4[i][zigzag_4x4[j]] = default_4x4_intra[j];
  18.429 +      }
  18.430 +      //memcpy(sps->scaling_lists_4x4[i], default_4x4_intra, sizeof(sps->scaling_lists_4x4[i]));
  18.431 +      break;
  18.432 +    }
  18.433 +    case 3: {
  18.434 +      for(j = 0; j < sizeof(default_4x4_inter); j++) {
  18.435 +        sps->scaling_lists_4x4[i][zigzag_4x4[j]] = default_4x4_inter[j];
  18.436 +      }
  18.437 +      //memcpy(sps->scaling_lists_4x4[i], default_4x4_inter, sizeof(sps->scaling_lists_4x4[i]));
  18.438 +      break;
  18.439 +    }
  18.440 +    case 1:
  18.441 +    case 2:
  18.442 +    case 4:
  18.443 +    case 5:
  18.444 +      memcpy(sps->scaling_lists_4x4[i], sps->scaling_lists_4x4[i-1], sizeof(sps->scaling_lists_4x4[i]));
  18.445 +      break;
  18.446 +    case 6: {
  18.447 +      for(j = 0; j < sizeof(default_8x8_intra); j++) {
  18.448 +        sps->scaling_lists_8x8[i-6][zigzag_8x8[j]] = default_8x8_intra[j];
  18.449 +      }
  18.450 +      //memcpy(sps->scaling_lists_8x8[i-6], default_8x8_intra, sizeof(sps->scaling_lists_8x8[i-6]));
  18.451 +      break;
  18.452 +    }
  18.453 +    case 7: {
  18.454 +      for(j = 0; j < sizeof(default_8x8_inter); j++) {
  18.455 +        sps->scaling_lists_8x8[i-6][zigzag_8x8[j]] = default_8x8_inter[j];
  18.456 +      }
  18.457 +      //memcpy(sps->scaling_lists_8x8[i-6], default_8x8_inter, sizeof(sps->scaling_lists_8x8[i-6]));
  18.458 +      break;
  18.459 +    }
  18.460 +
  18.461 +  }
  18.462 +}
  18.463 +
  18.464 +static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct pic_parameter_set_rbsp *pps, int i)
  18.465 +{
  18.466 +  switch (i) {
  18.467 +    case 0:
  18.468 +    case 3:
  18.469 +      memcpy(pps->scaling_lists_4x4[i], sps->scaling_lists_4x4[i], sizeof(pps->scaling_lists_4x4[i]));
  18.470 +      break;
  18.471 +    case 1:
  18.472 +    case 2:
  18.473 +    case 4:
  18.474 +    case 5:
  18.475 +      memcpy(pps->scaling_lists_4x4[i], pps->scaling_lists_4x4[i-1], sizeof(pps->scaling_lists_4x4[i]));
  18.476 +      break;
  18.477 +    case 6:
  18.478 +    case 7:
  18.479 +      memcpy(pps->scaling_lists_8x8[i-6], sps->scaling_lists_8x8[i-6], sizeof(pps->scaling_lists_8x8[i-6]));
  18.480 +      break;
  18.481 +
  18.482 +  }
  18.483 +}
  18.484 +
  18.485 +
  18.486 +uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser)
  18.487 +{
  18.488 +  struct seq_parameter_set_rbsp *sps = parser->current_nal->sps;
  18.489 +  sps->profile_idc = read_bits(buf, 8);
  18.490 +  sps->constraint_setN_flag = read_bits(buf, 4);
  18.491 +  read_bits(buf, 4);
  18.492 +  sps->level_idc = read_bits(buf, 8);
  18.493 +
  18.494 +  sps->seq_parameter_set_id = read_exp_golomb(buf);
  18.495 +
  18.496 +  memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4));
  18.497 +  memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_8x8));
  18.498 +  if (sps->profile_idc == 100 || sps->profile_idc == 110 || sps->profile_idc
  18.499 +      == 122 || sps->profile_idc == 244 || sps->profile_idc == 44 ||
  18.500 +      sps->profile_idc == 83 || sps->profile_idc == 86) {
  18.501 +    sps->chroma_format_idc = read_exp_golomb(buf);
  18.502 +    if (sps->chroma_format_idc == 3) {
  18.503 +      sps->separate_colour_plane_flag = read_bits(buf, 1);
  18.504 +    }
  18.505 +
  18.506 +    sps->bit_depth_luma_minus8 = read_exp_golomb(buf);
  18.507 +    sps->bit_depth_chroma_minus8 = read_exp_golomb(buf);
  18.508 +    sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1);
  18.509 +    sps->seq_scaling_matrix_present_flag = read_bits(buf, 1);
  18.510 +    if (sps->seq_scaling_matrix_present_flag) {
  18.511 +      int i;
  18.512 +      for (i = 0; i < 8; i++) {
  18.513 +        sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1);
  18.514 +
  18.515 +        if (sps->seq_scaling_list_present_flag[i]) {
  18.516 +          if (i < 6)
  18.517 +            parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i);
  18.518 +          else
  18.519 +            parse_scaling_list(buf, sps->scaling_lists_8x8[i - 6], 64, i);
  18.520 +        } else {
  18.521 +          sps_scaling_list_fallback(sps, i);
  18.522 +        }
  18.523 +      }
  18.524 +    }
  18.525 +  } else
  18.526 +    sps->chroma_format_idc = 1;
  18.527 +
  18.528 +  sps->log2_max_frame_num_minus4 = read_exp_golomb(buf);
  18.529 +
  18.530 +  sps->pic_order_cnt_type = read_exp_golomb(buf);
  18.531 +  if (!sps->pic_order_cnt_type)
  18.532 +    sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf);
  18.533 +  else if(sps->pic_order_cnt_type == 1) {
  18.534 +    sps->delta_pic_order_always_zero_flag = read_bits(buf, 1);
  18.535 +    sps->offset_for_non_ref_pic = read_exp_golomb_s(buf);
  18.536 +    sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf);
  18.537 +    sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf);
  18.538 +    int i;
  18.539 +    for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) {
  18.540 +      sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf);
  18.541 +    }
  18.542 +  }
  18.543 +
  18.544 +  sps->num_ref_frames = read_exp_golomb(buf);
  18.545 +  sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1);
  18.546 +
  18.547 +  /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf);
  18.548 +   sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/
  18.549 +  sps->pic_width = 16 * (read_exp_golomb(buf) + 1);
  18.550 +  sps->pic_height = 16 * (read_exp_golomb(buf) + 1);
  18.551 +
  18.552 +  sps->frame_mbs_only_flag = read_bits(buf, 1);
  18.553 +
  18.554 +  /* compute the height correctly even for interlaced material */
  18.555 +  sps->pic_height = (2 - sps->frame_mbs_only_flag) * sps->pic_height;
  18.556 +  if (sps->pic_height == 1088)
  18.557 +    sps->pic_height = 1080;
  18.558 +
  18.559 +  if (!sps->frame_mbs_only_flag)
  18.560 +    sps->mb_adaptive_frame_field_flag = read_bits(buf, 1);
  18.561 +
  18.562 +  sps->direct_8x8_inference_flag = read_bits(buf, 1);
  18.563 +  sps->frame_cropping_flag = read_bits(buf, 1);
  18.564 +  if (sps->frame_cropping_flag) {
  18.565 +    sps->frame_crop_left_offset = read_exp_golomb(buf);
  18.566 +    sps->frame_crop_right_offset = read_exp_golomb(buf);
  18.567 +    sps->frame_crop_top_offset = read_exp_golomb(buf);
  18.568 +    sps->frame_crop_bottom_offset = read_exp_golomb(buf);
  18.569 +  }
  18.570 +  sps->vui_parameters_present_flag = read_bits(buf, 1);
  18.571 +  if (sps->vui_parameters_present_flag) {
  18.572 +    parse_vui_parameters(buf, sps);
  18.573 +    if(sps->vui_parameters.nal_hrd_parameters_present_flag ||
  18.574 +        sps->vui_parameters.vc1_hrd_parameters_present_flag) {
  18.575 +      parser->cpb_dpb_delays_present_flag = 1;
  18.576 +    } else
  18.577 +      parser->cpb_dpb_delays_present_flag = 0;
  18.578 +  } else
  18.579 +    parser->cpb_dpb_delays_present_flag = 0;
  18.580 +
  18.581 +  return 0;
  18.582 +}
  18.583 +
  18.584 +void parse_sei(struct buf_reader *buf, struct nal_parser *parser)
  18.585 +{
  18.586 +  struct sei_message *sei = &(parser->current_nal->sei);
  18.587 +  struct seq_parameter_set_rbsp *sps = parser->current_nal->sps;
  18.588 +  uint8_t tmp;
  18.589 +
  18.590 +  sei->payload_type = 0;
  18.591 +  while((tmp = read_bits(buf, 8)) == 0xff) {
  18.592 +    sei->payload_type += 255;
  18.593 +  }
  18.594 +  sei->last_payload_type_byte = tmp;
  18.595 +  sei->payload_type += sei->last_payload_type_byte;
  18.596 +
  18.597 +  sei->payload_size = 0;
  18.598 +  while((tmp = read_bits(buf, 8)) == 0xff) {
  18.599 +    sei->payload_size += 255;
  18.600 +  }
  18.601 +  sei->last_payload_size_byte = tmp;
  18.602 +  sei->payload_size += sei->last_payload_size_byte;
  18.603 +
  18.604 +  /* pic_timing */
  18.605 +  if(sei->payload_type == 1) {
  18.606 +    if(parser->cpb_dpb_delays_present_flag) {
  18.607 +      sei->pic_timing.cpb_removal_delay = read_bits(buf, 5);
  18.608 +      sei->pic_timing.dpb_output_delay = read_bits(buf, 5);
  18.609 +    }
  18.610 +
  18.611 +    if(sps && sps->vui_parameters_present_flag &&
  18.612 +        sps->vui_parameters.pic_struct_present_flag) {
  18.613 +      sei->pic_timing.pic_struct = read_bits(buf, 4);
  18.614 +      switch(sei->pic_timing.pic_struct) {
  18.615 +        case DISP_FRAME:
  18.616 +          parser->current_nal->interlaced = 0;
  18.617 +          parser->current_nal->repeat_pic = 0;
  18.618 +          break;
  18.619 +        case DISP_TOP:
  18.620 +        case DISP_BOTTOM:
  18.621 +        case DISP_TOP_BOTTOM:
  18.622 +        case DISP_BOTTOM_TOP:
  18.623 +          parser->current_nal->interlaced = 1;
  18.624 +          break;
  18.625 +        case DISP_TOP_BOTTOM_TOP:
  18.626 +        case DISP_BOTTOM_TOP_BOTTOM:
  18.627 +          parser->current_nal->interlaced = 1;
  18.628 +          parser->current_nal->repeat_pic = 1;
  18.629 +          break;
  18.630 +        case DISP_FRAME_DOUBLING:
  18.631 +          parser->current_nal->interlaced = 0;
  18.632 +          parser->current_nal->repeat_pic = 2;
  18.633 +          break;
  18.634 +        case DISP_FRAME_TRIPLING:
  18.635 +          parser->current_nal->interlaced = 0;
  18.636 +          parser->current_nal->repeat_pic = 3;
  18.637 +      }
  18.638 +    }
  18.639 +  }
  18.640 +}
  18.641 +
  18.642 +void parse_vui_parameters(struct buf_reader *buf,
  18.643 +    struct seq_parameter_set_rbsp *sps)
  18.644 +{
  18.645 +  sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1);
  18.646 +  if (sps->vui_parameters.aspect_ration_info_present_flag == 1) {
  18.647 +    sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8);
  18.648 +    if (sps->vui_parameters.aspect_ratio_idc == ASPECT_EXTENDED_SAR) {
  18.649 +      sps->vui_parameters.sar_width = read_bits(buf, 16);
  18.650 +      sps->vui_parameters.sar_height = read_bits(buf, 16);
  18.651 +    }
  18.652 +  }
  18.653 +
  18.654 +  sps->vui_parameters.overscan_info_present_flag = read_bits(buf, 1);
  18.655 +  if (sps->vui_parameters.overscan_info_present_flag) {
  18.656 +    sps->vui_parameters.overscan_appropriate_flag = read_bits(buf, 1);
  18.657 +  }
  18.658 +
  18.659 +  sps->vui_parameters.video_signal_type_present_flag = read_bits(buf, 1);
  18.660 +  if (sps->vui_parameters.video_signal_type_present_flag) {
  18.661 +    sps->vui_parameters.video_format = read_bits(buf, 3);
  18.662 +    sps->vui_parameters.video_full_range_flag = read_bits(buf, 1);
  18.663 +    sps->vui_parameters.colour_description_present = read_bits(buf, 1);
  18.664 +    if (sps->vui_parameters.colour_description_present) {
  18.665 +      sps->vui_parameters.colour_primaries = read_bits(buf, 8);
  18.666 +      sps->vui_parameters.transfer_characteristics = read_bits(buf, 8);
  18.667 +      sps->vui_parameters.matrix_coefficients = read_bits(buf, 8);
  18.668 +    }
  18.669 +  }
  18.670 +
  18.671 +  sps->vui_parameters.chroma_loc_info_present_flag = read_bits(buf, 1);
  18.672 +  if (sps->vui_parameters.chroma_loc_info_present_flag) {
  18.673 +    sps->vui_parameters.chroma_sample_loc_type_top_field = read_exp_golomb(buf);
  18.674 +    sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb(
  18.675 +        buf);
  18.676 +  }
  18.677 +
  18.678 +  sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1);
  18.679 +  if (sps->vui_parameters.timing_info_present_flag) {
  18.680 +    uint32_t num_units_in_tick = read_bits(buf, 32);
  18.681 +    uint32_t time_scale = read_bits(buf, 32);
  18.682 +    sps->vui_parameters.num_units_in_tick = num_units_in_tick;
  18.683 +    sps->vui_parameters.time_scale = time_scale;
  18.684 +    sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1);
  18.685 +  }
  18.686 +
  18.687 +  sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1);
  18.688 +  if (sps->vui_parameters.nal_hrd_parameters_present_flag)
  18.689 +    parse_hrd_parameters(buf, &sps->vui_parameters.nal_hrd_parameters);
  18.690 +
  18.691 +  sps->vui_parameters.vc1_hrd_parameters_present_flag = read_bits(buf, 1);
  18.692 +  if (sps->vui_parameters.vc1_hrd_parameters_present_flag)
  18.693 +    parse_hrd_parameters(buf, &sps->vui_parameters.vc1_hrd_parameters);
  18.694 +
  18.695 +  if (sps->vui_parameters.nal_hrd_parameters_present_flag
  18.696 +      || sps->vui_parameters.vc1_hrd_parameters_present_flag)
  18.697 +    sps->vui_parameters.low_delay_hrd_flag = read_bits(buf, 1);
  18.698 +
  18.699 +  sps->vui_parameters.pic_struct_present_flag = read_bits(buf, 1);
  18.700 +  sps->vui_parameters.bitstream_restriction_flag = read_bits(buf, 1);
  18.701 +
  18.702 +  if (sps->vui_parameters.bitstream_restriction_flag) {
  18.703 +    sps->vui_parameters.motion_vectors_over_pic_boundaries = read_bits(buf, 1);
  18.704 +    sps->vui_parameters.max_bytes_per_pic_denom = read_exp_golomb(buf);
  18.705 +    sps->vui_parameters.max_bits_per_mb_denom = read_exp_golomb(buf);
  18.706 +    sps->vui_parameters.log2_max_mv_length_horizontal = read_exp_golomb(buf);
  18.707 +    sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf);
  18.708 +    sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf);
  18.709 +    sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf);
  18.710 +  }
  18.711 +}
  18.712 +
  18.713 +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd)
  18.714 +{
  18.715 +  hrd->cpb_cnt_minus1 = read_exp_golomb(buf);
  18.716 +  hrd->bit_rate_scale = read_bits(buf, 4);
  18.717 +  hrd->cpb_size_scale = read_bits(buf, 4);
  18.718 +
  18.719 +  int i;
  18.720 +  for (i = 0; i <= hrd->cpb_cnt_minus1; i++) {
  18.721 +    hrd->bit_rate_value_minus1[i] = read_exp_golomb(buf);
  18.722 +    hrd->cpb_size_value_minus1[i] = read_exp_golomb(buf);
  18.723 +    hrd->cbr_flag[i] = read_bits(buf, 1);
  18.724 +  }
  18.725 +
  18.726 +  hrd->initial_cpb_removal_delay_length_minus1 = read_bits(buf, 5);
  18.727 +  hrd->cpb_removal_delay_length_minus1 = read_bits(buf, 5);
  18.728 +  hrd->dpb_output_delay_length_minus1 = read_bits(buf, 5);
  18.729 +  hrd->time_offset_length = read_bits(buf, 5);
  18.730 +}
  18.731 +
  18.732 +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps,
  18.733 +    struct seq_parameter_set_rbsp *sps)
  18.734 +{
  18.735 +  pps->pic_parameter_set_id = read_exp_golomb(buf);
  18.736 +  pps->seq_parameter_set_id = read_exp_golomb(buf);
  18.737 +  pps->entropy_coding_mode_flag = read_bits(buf, 1);
  18.738 +  pps->pic_order_present_flag = read_bits(buf, 1);
  18.739 +
  18.740 +  pps->num_slice_groups_minus1 = read_exp_golomb(buf);
  18.741 +  if (pps->num_slice_groups_minus1 > 0) {
  18.742 +    pps->slice_group_map_type = read_exp_golomb(buf);
  18.743 +    if (pps->slice_group_map_type == 0) {
  18.744 +      int i_group;
  18.745 +      for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) {
  18.746 +        if (i_group < 64)
  18.747 +          pps->run_length_minus1[i_group] = read_exp_golomb(buf);
  18.748 +        else { // FIXME: skips if more than 64 groups exist
  18.749 +          fprintf(stderr, "Error: Only 64 slice_groups are supported\n");
  18.750 +          read_exp_golomb(buf);
  18.751 +        }
  18.752 +      }
  18.753 +    }
  18.754 +    else if (pps->slice_group_map_type == 3 || pps->slice_group_map_type == 4
  18.755 +        || pps->slice_group_map_type == 5) {
  18.756 +      pps->slice_group_change_direction_flag = read_bits(buf, 1);
  18.757 +      pps->slice_group_change_rate_minus1 = read_exp_golomb(buf);
  18.758 +    }
  18.759 +    else if (pps->slice_group_map_type == 6) {
  18.760 +      pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf);
  18.761 +      int i_group;
  18.762 +      for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) {
  18.763 +        pps->slice_group_id[i_group] = read_bits(buf, ceil(log(
  18.764 +            pps->num_slice_groups_minus1 + 1)));
  18.765 +      }
  18.766 +    }
  18.767 +  }
  18.768 +
  18.769 +  pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf);
  18.770 +  pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf);
  18.771 +  pps->weighted_pred_flag = read_bits(buf, 1);
  18.772 +  pps->weighted_bipred_idc = read_bits(buf, 2);
  18.773 +  pps->pic_init_qp_minus26 = read_exp_golomb_s(buf);
  18.774 +  pps->pic_init_qs_minus26 = read_exp_golomb_s(buf);
  18.775 +  pps->chroma_qp_index_offset = read_exp_golomb_s(buf);
  18.776 +  pps->deblocking_filter_control_present_flag = read_bits(buf, 1);
  18.777 +  pps->constrained_intra_pred_flag = read_bits(buf, 1);
  18.778 +  pps->redundant_pic_cnt_present_flag = read_bits(buf, 1);
  18.779 +
  18.780 +  int bit_length = (buf->len*8)-rbsp_trailing_bits(buf->buf, buf->len);
  18.781 +  int bit_read = bits_read(buf);
  18.782 +
  18.783 +  memset(pps->scaling_lists_4x4, 16, sizeof(pps->scaling_lists_4x4));
  18.784 +  memset(pps->scaling_lists_8x8, 16, sizeof(pps->scaling_lists_8x8));
  18.785 +  if (bit_length-bit_read > 1) {
  18.786 +    pps->transform_8x8_mode_flag = read_bits(buf, 1);
  18.787 +    pps->pic_scaling_matrix_present_flag = read_bits(buf, 1);
  18.788 +    if (pps->pic_scaling_matrix_present_flag) {
  18.789 +      int i;
  18.790 +      for (i = 0; i < 8; i++) {
  18.791 +        if(i < 6 || pps->transform_8x8_mode_flag)
  18.792 +          pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1);
  18.793 +        else
  18.794 +          pps->pic_scaling_list_present_flag[i] = 0;
  18.795 +
  18.796 +        if (pps->pic_scaling_list_present_flag[i]) {
  18.797 +          if (i < 6)
  18.798 +            parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i);
  18.799 +          else
  18.800 +            parse_scaling_list(buf, pps->scaling_lists_8x8[i - 6], 64, i);
  18.801 +        } else {
  18.802 +          pps_scaling_list_fallback(sps, pps, i);
  18.803 +        }
  18.804 +      }
  18.805 +    }
  18.806 +
  18.807 +    pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf);
  18.808 +  } else
  18.809 +    pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset;
  18.810 +
  18.811 +  if (!pps->pic_scaling_matrix_present_flag && sps != NULL) {
  18.812 +    memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4,
  18.813 +        sizeof(pps->scaling_lists_4x4));
  18.814 +    memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8,
  18.815 +        sizeof(pps->scaling_lists_8x8));
  18.816 +  }
  18.817 +
  18.818 +  return 0;
  18.819 +}
  18.820 +
  18.821 +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser)
  18.822 +{
  18.823 +  struct nal_unit *nal = parser->current_nal;
  18.824 +
  18.825 +  struct seq_parameter_set_rbsp *sps = nal->sps;
  18.826 +  struct pic_parameter_set_rbsp *pps = nal->pps;
  18.827 +  struct slice_header *slc = nal->slc;
  18.828 +  memset(slc, 0x00, sizeof(struct slice_header));
  18.829 +  if (!sps || !pps)
  18.830 +    return -1;
  18.831 +
  18.832 +  slc->first_mb_in_slice = read_exp_golomb(buf);
  18.833 +  /* we do some parsing on the slice type, because the list is doubled */
  18.834 +  slc->slice_type = slice_type(read_exp_golomb(buf));
  18.835 +
  18.836 +  //print_slice_type(slc->slice_type);
  18.837 +  slc->pic_parameter_set_id = read_exp_golomb(buf);
  18.838 +  if(sps->separate_colour_plane_flag)
  18.839 +    slc->colour_plane_id = read_bits(buf, 2);
  18.840 +
  18.841 +  slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4);
  18.842 +  if (!sps->frame_mbs_only_flag) {
  18.843 +    slc->field_pic_flag = read_bits(buf, 1);
  18.844 +    if (slc->field_pic_flag)
  18.845 +      slc->bottom_field_flag = read_bits(buf, 1);
  18.846 +    else
  18.847 +      slc->bottom_field_flag = 0;
  18.848 +  }
  18.849 +  else {
  18.850 +    slc->field_pic_flag = 0;
  18.851 +    slc->bottom_field_flag = 0;
  18.852 +  }
  18.853 +
  18.854 +  if (slc->field_pic_flag == 0) {
  18.855 +    nal->max_pic_num = 1 << (sps->log2_max_frame_num_minus4+4);
  18.856 +    nal->curr_pic_num = slc->frame_num;
  18.857 +  } else {
  18.858 +    nal->curr_pic_num = 2 * slc->frame_num + 1;
  18.859 +    nal->max_pic_num = 2 * (1 << (sps->log2_max_frame_num_minus4+4));
  18.860 +  }
  18.861 +
  18.862 +  if (nal->nal_unit_type == NAL_SLICE_IDR)
  18.863 +    slc->idr_pic_id = read_exp_golomb(buf);
  18.864 +
  18.865 +  if (!sps->pic_order_cnt_type) {
  18.866 +    slc->pic_order_cnt_lsb = read_bits(buf,
  18.867 +        sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
  18.868 +    if (pps->pic_order_present_flag && !slc->field_pic_flag)
  18.869 +      slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf);
  18.870 +  }
  18.871 +
  18.872 +  if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) {
  18.873 +    slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf);
  18.874 +    if (pps->pic_order_present_flag && !slc->field_pic_flag)
  18.875 +      slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf);
  18.876 +  }
  18.877 +
  18.878 +  if (pps->redundant_pic_cnt_present_flag == 1) {
  18.879 +    slc->redundant_pic_cnt = read_exp_golomb(buf);
  18.880 +  }
  18.881 +
  18.882 +  if (slc->slice_type == SLICE_B)
  18.883 +    slc->direct_spatial_mv_pred_flag = read_bits(buf, 1);
  18.884 +
  18.885 +  /* take default values in case they are not set here */
  18.886 +  slc->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1;
  18.887 +  slc->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1;
  18.888 +
  18.889 +  if (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP
  18.890 +      || slc->slice_type == SLICE_B) {
  18.891 +    slc->num_ref_idx_active_override_flag = read_bits(buf, 1);
  18.892 +
  18.893 +    if (slc->num_ref_idx_active_override_flag == 1) {
  18.894 +      slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf);
  18.895 +
  18.896 +      if (slc->slice_type == SLICE_B) {
  18.897 +        slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf);
  18.898 +      }
  18.899 +    }
  18.900 +  }
  18.901 +
  18.902 +  /* --- ref_pic_list_reordering --- */
  18.903 +  parse_ref_pic_list_reordering(buf, nal, parser);
  18.904 +
  18.905 +  /* --- pred_weight_table --- */
  18.906 +  if ((pps->weighted_pred_flag && (slc->slice_type == SLICE_P
  18.907 +      || slc->slice_type == SLICE_SP)) || (pps->weighted_bipred_idc == 1
  18.908 +      && slc->slice_type == SLICE_B)) {
  18.909 +    parse_pred_weight_table(buf, nal);
  18.910 +  }
  18.911 +
  18.912 +  /* --- dec_ref_pic_marking --- */
  18.913 +  if (nal->nal_ref_idc != 0)
  18.914 +    parse_dec_ref_pic_marking(buf, parser);
  18.915 +  else
  18.916 +    slc->dec_ref_pic_marking_count = 0;
  18.917 +
  18.918 +  return 0;
  18.919 +}
  18.920 +
  18.921 +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, struct nal_parser *parser)
  18.922 +{
  18.923 +  struct slice_header *slc = nal->slc;
  18.924 +
  18.925 +  if (slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) {
  18.926 +    slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits(
  18.927 +        buf, 1);
  18.928 +
  18.929 +    if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) {
  18.930 +      do {
  18.931 +        slc->ref_pic_list_reordering.reordering_of_pic_nums_idc
  18.932 +            = read_exp_golomb(buf);
  18.933 +
  18.934 +        if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0
  18.935 +            || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) {
  18.936 +          slc->ref_pic_list_reordering.abs_diff_pic_num_minus1
  18.937 +              = read_exp_golomb(buf);
  18.938 +        }
  18.939 +        else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) {
  18.940 +          slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf);
  18.941 +        }
  18.942 +      } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3);
  18.943 +    }
  18.944 +  }
  18.945 +
  18.946 +  if (slc->slice_type == SLICE_B) {
  18.947 +    slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits(
  18.948 +        buf, 1);
  18.949 +
  18.950 +    if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) {
  18.951 +      do {
  18.952 +        slc->ref_pic_list_reordering.reordering_of_pic_nums_idc
  18.953 +            = read_exp_golomb(buf);
  18.954 +
  18.955 +        if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0
  18.956 +            || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) {
  18.957 +          slc->ref_pic_list_reordering.abs_diff_pic_num_minus1
  18.958 +              = read_exp_golomb(buf);
  18.959 +        }
  18.960 +        else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) {
  18.961 +          slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf);
  18.962 +        }
  18.963 +      } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3);
  18.964 +    }
  18.965 +  }
  18.966 +}
  18.967 +
  18.968 +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal)
  18.969 +{
  18.970 +  struct seq_parameter_set_rbsp *sps = nal->sps;
  18.971 +  struct pic_parameter_set_rbsp *pps = nal->pps;
  18.972 +  struct slice_header *slc = nal->slc;
  18.973 +  if (!sps || !pps)
  18.974 +    return;
  18.975 +
  18.976 +  nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf);
  18.977 +
  18.978 +  uint32_t ChromaArrayType = sps->chroma_format_idc;
  18.979 +  if(sps->separate_colour_plane_flag)
  18.980 +    ChromaArrayType = 0;
  18.981 +
  18.982 +  if (ChromaArrayType != 0)
  18.983 +    nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf);
  18.984 +
  18.985 +  int i;
  18.986 +  for (i = 0; i <= slc->num_ref_idx_l0_active_minus1; i++) {
  18.987 +    uint8_t luma_weight_l0_flag = read_bits(buf, 1);
  18.988 +
  18.989 +    if (luma_weight_l0_flag == 1) {
  18.990 +      nal->slc->pred_weight_table.luma_weight_l0[i] = read_exp_golomb_s(buf);
  18.991 +      nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf);
  18.992 +    }
  18.993 +
  18.994 +    if (ChromaArrayType != 0) {
  18.995 +      uint8_t chroma_weight_l0_flag = read_bits(buf, 1);
  18.996 +
  18.997 +      if (chroma_weight_l0_flag == 1) {
  18.998 +        int j;
  18.999 +        for (j = 0; j < 2; j++) {
 18.1000 +          nal->slc->pred_weight_table.chroma_weight_l0[i][j]
 18.1001 +              = read_exp_golomb_s(buf);
 18.1002 +          nal->slc->pred_weight_table.chroma_offset_l0[i][j]
 18.1003 +              = read_exp_golomb_s(buf);
 18.1004 +        }
 18.1005 +      }
 18.1006 +    }
 18.1007 +  }
 18.1008 +
 18.1009 +  if ((slc->slice_type % 5) == SLICE_B) {
 18.1010 +    /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1
 18.1011 +     * will break Divx7 files. Keep this in mind if any other streams are broken
 18.1012 +     */
 18.1013 +    for (i = 0; i <= slc->num_ref_idx_l1_active_minus1; i++) {
 18.1014 +      uint8_t luma_weight_l1_flag = read_bits(buf, 1);
 18.1015 +
 18.1016 +      if (luma_weight_l1_flag == 1) {
 18.1017 +        nal->slc->pred_weight_table.luma_weight_l1[i] = read_exp_golomb_s(buf);
 18.1018 +        nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf);
 18.1019 +      }
 18.1020 +
 18.1021 +      if (ChromaArrayType != 0) {
 18.1022 +        uint8_t chroma_weight_l1_flag = read_bits(buf, 1);
 18.1023 +
 18.1024 +        if (chroma_weight_l1_flag == 1) {
 18.1025 +          int j;
 18.1026 +          for (j = 0; j < 2; j++) {
 18.1027 +            nal->slc->pred_weight_table.chroma_weight_l1[i][j]
 18.1028 +                = read_exp_golomb_s(buf);
 18.1029 +            nal->slc->pred_weight_table.chroma_offset_l1[i][j]
 18.1030 +                = read_exp_golomb_s(buf);
 18.1031 +          }
 18.1032 +        }
 18.1033 +      }
 18.1034 +    }
 18.1035 +  }
 18.1036 +}
 18.1037 +
 18.1038 +void decode_ref_pic_marking(struct nal_unit *nal,
 18.1039 +    uint32_t memory_management_control_operation,
 18.1040 +    uint32_t marking_nr,
 18.1041 +    struct nal_parser *parser)
 18.1042 +{
 18.1043 +  struct slice_header *slc = nal->slc;
 18.1044 +  struct dpb *dpb = &parser->dpb;
 18.1045 +  if (!slc)
 18.1046 +    return;
 18.1047 +
 18.1048 +  if (memory_management_control_operation == 1) {
 18.1049 +    // short-term -> unused for reference
 18.1050 +    uint32_t pic_num_x = (nal->curr_pic_num
 18.1051 +        - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1))%nal->max_pic_num;
 18.1052 +    struct decoded_picture* pic = NULL;
 18.1053 +    if ((pic = dpb_get_picture(dpb, pic_num_x)) != NULL) {
 18.1054 +      if (pic->nal->slc->field_pic_flag == 0) {
 18.1055 +        dpb_set_unused_ref_picture_a(dpb, pic);
 18.1056 +      } else {
 18.1057 +        //if(!pic->top_is_reference)
 18.1058 +          dpb_set_unused_ref_picture_a(dpb, pic);
 18.1059 +        /*else
 18.1060 +          pic->top_is_reference = 0;*/
 18.1061 +
 18.1062 +        //printf("FIXME: We might need do delete more from the DPB...\n");
 18.1063 +        // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120
 18.1064 +      }
 18.1065 +    }
 18.1066 +  } else if (memory_management_control_operation == 2) {
 18.1067 +    // long-term -> unused for reference
 18.1068 +    struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb,
 18.1069 +        slc->dec_ref_pic_marking[marking_nr].long_term_pic_num);
 18.1070 +    if (pic != NULL) {
 18.1071 +      if (pic->nal->slc->field_pic_flag == 0)
 18.1072 +        dpb_set_unused_ref_picture(dpb,
 18.1073 +            slc->dec_ref_pic_marking[marking_nr].long_term_pic_num);
 18.1074 +      else {
 18.1075 +        dpb_set_unused_ref_picture(dpb,
 18.1076 +            slc->dec_ref_pic_marking[marking_nr].long_term_pic_num);
 18.1077 +        printf("FIXME: We might need do delete more from the DPB...\n");
 18.1078 +      }
 18.1079 +    }
 18.1080 +  } else if (memory_management_control_operation == 3) {
 18.1081 +    // short-term -> long-term, set long-term frame index
 18.1082 +    uint32_t pic_num_x = nal->curr_pic_num
 18.1083 +        - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1);
 18.1084 +    struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb,
 18.1085 +        slc->dec_ref_pic_marking[marking_nr].long_term_pic_num);
 18.1086 +    if (pic != NULL)
 18.1087 +      dpb_set_unused_ref_picture_bylidx(dpb,
 18.1088 +          slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx);
 18.1089 +
 18.1090 +    pic = dpb_get_picture(dpb, pic_num_x);
 18.1091 +    if (pic) {
 18.1092 +      if (pic->nal->slc->field_pic_flag == 0) {
 18.1093 +        pic = dpb_get_picture(dpb, pic_num_x);
 18.1094 +        pic->nal->long_term_frame_idx
 18.1095 +            = slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx;
 18.1096 +      }
 18.1097 +      else
 18.1098 +        printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x);
 18.1099 +    }
 18.1100 +    else {
 18.1101 +      printf("memory_management_control_operation: 3 failed. No such picture.\n");
 18.1102 +    }
 18.1103 +
 18.1104 +  } else if (memory_management_control_operation == 4) {
 18.1105 +    // set max-long-term frame index,
 18.1106 +    // mark all long-term pictures with long-term frame idx
 18.1107 +    // greater max-long-term farme idx as unused for ref
 18.1108 +    if (slc->dec_ref_pic_marking[marking_nr].max_long_term_frame_idx_plus1 == 0)
 18.1109 +      dpb_set_unused_ref_picture_lidx_gt(dpb, 0);
 18.1110 +    else
 18.1111 +      dpb_set_unused_ref_picture_lidx_gt(dpb,
 18.1112 +          slc->dec_ref_pic_marking[marking_nr].max_long_term_frame_idx_plus1 - 1);
 18.1113 +  } else if (memory_management_control_operation == 5) {
 18.1114 +    // mark all ref pics as unused for reference,
 18.1115 +    // set max-long-term frame index = no long-term frame idxs
 18.1116 +    dpb_flush(dpb);
 18.1117 +    parser->pic_order_cnt_lsb = 0;
 18.1118 +    parser->pic_order_cnt_msb = 0;
 18.1119 +    parser->prev_pic_order_cnt_lsb = 0;
 18.1120 +    parser->prev_pic_order_cnt_msb = 0;
 18.1121 +  } else if (memory_management_control_operation == 6) {
 18.1122 +    // mark current picture as used for long-term ref,
 18.1123 +    // assing long-term frame idx to it
 18.1124 +    struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb,
 18.1125 +        slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx);
 18.1126 +    if (pic != NULL)
 18.1127 +      dpb_set_unused_ref_picture_bylidx(dpb,
 18.1128 +          slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx);
 18.1129 +
 18.1130 +    nal->long_term_frame_idx = slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx;
 18.1131 +
 18.1132 +    if (slc->field_pic_flag == 0) {
 18.1133 +      nal->used_for_long_term_ref = 1;
 18.1134 +    }
 18.1135 +    else
 18.1136 +      printf("FIXME: BY Set frame to long-term ref\n");
 18.1137 +  }
 18.1138 +  /* FIXME: Do we need to care about MMC=0? */
 18.1139 +}
 18.1140 +
 18.1141 +void parse_dec_ref_pic_marking(struct buf_reader *buf,
 18.1142 +    struct nal_parser *parser)
 18.1143 +{
 18.1144 +  struct nal_unit *nal = parser->current_nal;
 18.1145 +  struct pic_parameter_set_rbsp *pps = parser->current_nal->pps;
 18.1146 +  struct slice_header *slc = nal->slc;
 18.1147 +
 18.1148 +  if (!slc || !pps)
 18.1149 +    return;
 18.1150 +
 18.1151 +  slc->dec_ref_pic_marking_count = 0;
 18.1152 +  int i = slc->dec_ref_pic_marking_count;
 18.1153 +
 18.1154 +  if (nal->nal_unit_type == NAL_SLICE_IDR) {
 18.1155 +    slc->dec_ref_pic_marking[i].no_output_of_prior_pics_flag = read_bits(buf, 1);
 18.1156 +    slc->dec_ref_pic_marking[i].long_term_reference_flag = read_bits(buf, 1);
 18.1157 +  } else {
 18.1158 +    slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag = read_bits(
 18.1159 +        buf, 1);
 18.1160 +
 18.1161 +    if (slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag) {
 18.1162 +      do {
 18.1163 +        slc->dec_ref_pic_marking[i].memory_management_control_operation
 18.1164 +            = read_exp_golomb(buf);
 18.1165 +
 18.1166 +        if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 1
 18.1167 +            || slc->dec_ref_pic_marking[i].memory_management_control_operation
 18.1168 +                == 3)
 18.1169 +          slc->dec_ref_pic_marking[i].difference_of_pic_nums_minus1
 18.1170 +              = read_exp_golomb(buf);
 18.1171 +
 18.1172 +        if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 2)
 18.1173 +          slc->dec_ref_pic_marking[i].long_term_pic_num = read_exp_golomb(buf);
 18.1174 +
 18.1175 +        if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 3
 18.1176 +            || slc->dec_ref_pic_marking[i].memory_management_control_operation
 18.1177 +                == 6)
 18.1178 +          slc->dec_ref_pic_marking[i].long_term_frame_idx = read_exp_golomb(buf);
 18.1179 +
 18.1180 +        if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 4)
 18.1181 +          slc->dec_ref_pic_marking[i].max_long_term_frame_idx_plus1
 18.1182 +              = read_exp_golomb(buf);
 18.1183 +
 18.1184 +        i++;
 18.1185 +        if(i >= 10) {
 18.1186 +          printf("Error: Not more than 10 MMC operations supported per slice. Dropping some.\n");
 18.1187 +          i = 0;
 18.1188 +        }
 18.1189 +      } while (slc->dec_ref_pic_marking[i-1].memory_management_control_operation
 18.1190 +          != 0);
 18.1191 +    }
 18.1192 +  }
 18.1193 +
 18.1194 +  slc->dec_ref_pic_marking_count = (i>0) ? (i-1) : 0;
 18.1195 +}
 18.1196 +
 18.1197 +/* ----------------- NAL parser ----------------- */
 18.1198 +
 18.1199 +struct nal_parser* init_parser()
 18.1200 +{
 18.1201 +  struct nal_parser *parser = calloc(1, sizeof(struct nal_parser));
 18.1202 +  parser->nal0 = init_nal_unit();
 18.1203 +  parser->nal1 = init_nal_unit();
 18.1204 +  parser->current_nal = parser->nal0;
 18.1205 +  parser->last_nal = parser->nal1;
 18.1206 +  parser->slice_cnt = 1;
 18.1207 +
 18.1208 +  parser->field = -1;
 18.1209 +
 18.1210 +  /* no idea why we do that. inspired by libavcodec,
 18.1211 +   * as we couldn't figure in the specs....
 18.1212 +   */
 18.1213 +  parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_lsb = 1 << 16;
 18.1214 +
 18.1215 +  return parser;
 18.1216 +}
 18.1217 +
 18.1218 +void free_parser(struct nal_parser *parser)
 18.1219 +{
 18.1220 +  free_nal_unit(parser->nal0);
 18.1221 +  free_nal_unit(parser->nal1);
 18.1222 +  free(parser);
 18.1223 +}
 18.1224 +
 18.1225 +void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len)
 18.1226 +{
 18.1227 +  struct buf_reader bufr;
 18.1228 +
 18.1229 +  bufr.buf = inbuf;
 18.1230 +  bufr.cur_pos = inbuf;
 18.1231 +  bufr.cur_offset = 8;
 18.1232 +  bufr.len = inbuf_len;
 18.1233 +
 18.1234 +  struct nal_unit *nal = parser->current_nal;
 18.1235 +  struct nal_unit *nal1 = parser->last_nal;
 18.1236 +
 18.1237 +  if (!nal->sps)
 18.1238 +    nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp));
 18.1239 +  else
 18.1240 +    memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp));
 18.1241 +
 18.1242 +  /* reserved */
 18.1243 +  read_bits(&bufr, 8);
 18.1244 +  nal->sps->profile_idc = read_bits(&bufr, 8);
 18.1245 +  read_bits(&bufr, 8);
 18.1246 +  nal->sps->level_idc = read_bits(&bufr, 8);
 18.1247 +  read_bits(&bufr, 6);
 18.1248 +
 18.1249 +  parser->nal_size_length = read_bits(&bufr, 2) + 1;
 18.1250 +  parser->nal_size_length_buf = calloc(1, parser->nal_size_length);
 18.1251 +  read_bits(&bufr, 3);
 18.1252 +  uint8_t sps_count = read_bits(&bufr, 5);
 18.1253 +
 18.1254 +  inbuf += 6;
 18.1255 +  inbuf_len -= 6;
 18.1256 +  int i;
 18.1257 +  for(i = 0; i < sps_count; i++) {
 18.1258 +    uint16_t sps_size = read_bits(&bufr, 16);
 18.1259 +    inbuf += 2;
 18.1260 +    inbuf_len -= 2;
 18.1261 +    parse_nal(inbuf, sps_size, parser);
 18.1262 +    inbuf += sps_size;
 18.1263 +    inbuf_len -= sps_size;
 18.1264 +  }
 18.1265 +
 18.1266 +  bufr.buf = inbuf;
 18.1267 +  bufr.cur_pos = inbuf;
 18.1268 +  bufr.cur_offset = 8;
 18.1269 +  bufr.len = inbuf_len;
 18.1270 +
 18.1271 +  uint8_t pps_count = read_bits(&bufr, 8);
 18.1272 +  inbuf += 1;
 18.1273 +  for(i = 0; i < pps_count; i++) {
 18.1274 +    uint16_t pps_size = read_bits(&bufr, 16);
 18.1275 +    inbuf += 2;
 18.1276 +    inbuf_len -= 2;
 18.1277 +    parse_nal(inbuf, pps_size, parser);
 18.1278 +    inbuf += pps_size;
 18.1279 +    inbuf_len -= pps_size;
 18.1280 +  }
 18.1281 +
 18.1282 +  copy_nal_unit(nal1, nal);
 18.1283 +  printf("done parsing extradata\n");
 18.1284 +}
 18.1285 +
 18.1286 +void process_mmc_operations(struct nal_parser *parser)
 18.1287 +{
 18.1288 +  if(parser->last_nal_res == 1 && parser->current_nal &&
 18.1289 +        parser->current_nal->slc) {
 18.1290 +    int i;
 18.1291 +    for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) {
 18.1292 +      decode_ref_pic_marking(
 18.1293 +          parser->current_nal,
 18.1294 +          parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation,
 18.1295 +          i,
 18.1296 +          parser);
 18.1297 +    }
 18.1298 +
 18.1299 +    if (parser->last_nal->slc != NULL)
 18.1300 +      parser->prev_pic_order_cnt_lsb
 18.1301 +          = parser->last_nal->slc->pic_order_cnt_lsb;
 18.1302 +    parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb;
 18.1303 +  }
 18.1304 +}
 18.1305 +
 18.1306 +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
 18.1307 +    uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt)
 18.1308 +{
 18.1309 +  int32_t next_nal = 0;
 18.1310 +  int32_t offset = 0;
 18.1311 +  int start_seq_len = 3;
 18.1312 +
 18.1313 +  if(parser->nal_size_length > 0)
 18.1314 +    start_seq_len = offset = parser->nal_size_length;
 18.1315 +
 18.1316 +  if (parser->prebuf_len + inbuf_len > MAX_FRAME_SIZE) {
 18.1317 +    printf("buf underrun!!\n");
 18.1318 +    *ret_len = 0;
 18.1319 +    *ret_buf = NULL;
 18.1320 +    parser->prebuf_len = 0;
 18.1321 +    return inbuf_len;
 18.1322 +  }
 18.1323 +
 18.1324 +  /* copy the whole inbuf to the prebuf,
 18.1325 +   * then search for a nal-start sequence in the prebuf,
 18.1326 +   * if it's in there, parse the nal and append to parser->buf
 18.1327 +   * or return a frame */
 18.1328 +
 18.1329 +  xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len);
 18.1330 +  parser->prebuf_len += inbuf_len;
 18.1331 +
 18.1332 +  while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-start_seq_len+offset, parser)) > 0) {
 18.1333 +
 18.1334 +    if(!parser->nal_size_length &&
 18.1335 +        (parser->prebuf[0] != 0x00 || parser->prebuf[1] != 0x00 || parser->prebuf[2] != 0x01)) {
 18.1336 +      printf("Broken NAL, skip it.\n");
 18.1337 +      parser->last_nal_res = 2;
 18.1338 +    } else
 18.1339 +      parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, next_nal, parser);
 18.1340 +
 18.1341 +    if ((parser->last_nal_res == 1 || parser->last_nal_res == 3) && parser->buf_len > 0) {
 18.1342 +
 18.1343 +      //printf("Frame complete: %d bytes\n", parser->buf_len);
 18.1344 +      *ret_len = parser->buf_len;
 18.1345 +      *ret_buf = malloc(*ret_len);
 18.1346 +      xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len);
 18.1347 +      *ret_slice_cnt = parser->slice_cnt;
 18.1348 +
 18.1349 +      parser->slice_cnt = 1;
 18.1350 +      parser->buf_len = 0;
 18.1351 +
 18.1352 +      /* this is a SLICE, keep it in the buffer */
 18.1353 +
 18.1354 +      if(parser->last_nal_res != 3) {
 18.1355 +        if(parser->nal_size_length > 0) {
 18.1356 +          static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 };
 18.1357 +          xine_fast_memcpy(parser->buf, start_seq, 3);
 18.1358 +          parser->buf_len += 3;
 18.1359 +        }
 18.1360 +
 18.1361 +        xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset);
 18.1362 +        parser->buf_len += next_nal+start_seq_len-2*offset;
 18.1363 +      }
 18.1364 +
 18.1365 +      memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset));
 18.1366 +      parser->prebuf_len -= next_nal+start_seq_len-offset;
 18.1367 +
 18.1368 +      return inbuf_len;
 18.1369 +    }
 18.1370 +
 18.1371 +    /* got a new nal, which is part of the current
 18.1372 +     * coded picture. add it to buf
 18.1373 +     */
 18.1374 +    if (parser->last_nal_res < 2) {
 18.1375 +      if (parser->buf_len + next_nal+start_seq_len-offset > MAX_FRAME_SIZE) {
 18.1376 +        printf("buf underrun 1!!\n");
 18.1377 +        parser->buf_len = 0;
 18.1378 +        *ret_len = 0;
 18.1379 +        *ret_buf = NULL;
 18.1380 +        return inbuf_len;
 18.1381 +      }
 18.1382 +
 18.1383 +      if(parser->nal_size_length > 0) {
 18.1384 +        static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 };
 18.1385 +        xine_fast_memcpy(parser->buf+parser->buf_len, start_seq, 3);
 18.1386 +        parser->buf_len += 3;
 18.1387 +      }
 18.1388 +
 18.1389 +      xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset);
 18.1390 +      parser->buf_len += next_nal+start_seq_len-2*offset;
 18.1391 +
 18.1392 +      memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset));
 18.1393 +      parser->prebuf_len -= next_nal+start_seq_len-offset;
 18.1394 +    } else {
 18.1395 +      /* got a non-relevant nal, just remove it */
 18.1396 +      memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset));
 18.1397 +      parser->prebuf_len -= next_nal+start_seq_len-offset;
 18.1398 +    }
 18.1399 +  }
 18.1400 +
 18.1401 +  *ret_buf = NULL;
 18.1402 +  *ret_len = 0;
 18.1403 +  return inbuf_len;
 18.1404 +}
 18.1405 +
 18.1406 +
 18.1407 +/**
 18.1408 + * @return 0: NAL is part of coded picture
 18.1409 + *         2: NAL is not part of coded picture
 18.1410 + *         1: NAL is the beginning of a new coded picture
 18.1411 + *         3: NAL is marked as END_OF_SEQUENCE
 18.1412 + */
 18.1413 +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser)
 18.1414 +{
 18.1415 +  struct buf_reader bufr;
 18.1416 +
 18.1417 +  bufr.buf = buf;
 18.1418 +  bufr.cur_pos = buf;
 18.1419 +  bufr.cur_offset = 8;
 18.1420 +  bufr.len = buf_len;
 18.1421 +
 18.1422 +  struct nal_unit *nal = parser->current_nal;
 18.1423 +  struct nal_unit *last_nal = parser->last_nal;
 18.1424 +
 18.1425 +  int res = parse_nal_header(&bufr, parser);
 18.1426 +  if (res == NAL_SLICE_IDR) {
 18.1427 +    parser->is_idr = 1;
 18.1428 +  }
 18.1429 +
 18.1430 +  calculate_pic_order(parser);
 18.1431 +
 18.1432 +  if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) {
 18.1433 +    // now detect if it's a new frame!
 18.1434 +    int ret = 0;
 18.1435 +    uint8_t reason = 0;
 18.1436 +    if (nal->slc->field_pic_flag == 1)
 18.1437 +      parser->field = nal->slc->bottom_field_flag;
 18.1438 +    else {
 18.1439 +      parser->have_top = 1;
 18.1440 +      parser->field = -1;
 18.1441 +    }
 18.1442 +
 18.1443 +    if (nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0)
 18.1444 +      parser->have_top = 1;
 18.1445 +
 18.1446 +    parser->slice = 1;
 18.1447 +
 18.1448 +    if (nal->slc == NULL || last_nal->slc == NULL) {
 18.1449 +      ret = 1;
 18.1450 +      reason++;
 18.1451 +    }
 18.1452 +    if (nal->slc && last_nal->slc && (nal->slc->frame_num
 18.1453 +        != last_nal->slc->frame_num)) {
 18.1454 +      ret = 1;
 18.1455 +      reason++;
 18.1456 +    }
 18.1457 +    if (nal->slc && last_nal->slc && (nal->slc->pic_parameter_set_id
 18.1458 +        != last_nal->slc->pic_parameter_set_id)) {
 18.1459 +      ret = 1;
 18.1460 +      reason++;
 18.1461 +    }
 18.1462 +    if (nal->slc && last_nal->slc && (nal->slc->field_pic_flag
 18.1463 +        != last_nal->slc->field_pic_flag)) {
 18.1464 +      ret = 1;
 18.1465 +      reason++;
 18.1466 +    }
 18.1467 +    if (nal->slc && last_nal->slc && nal->slc->bottom_field_flag
 18.1468 +        != last_nal->slc->bottom_field_flag) {
 18.1469 +      ret = 1;
 18.1470 +      reason++;
 18.1471 +    }
 18.1472 +    if (nal->nal_ref_idc != last_nal->nal_ref_idc && (nal->nal_ref_idc == 0
 18.1473 +        || last_nal->nal_ref_idc == 0)) {
 18.1474 +      ret = 1;
 18.1475 +      reason++;
 18.1476 +    }
 18.1477 +    if (nal->sps && nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type
 18.1478 +        == 0 && last_nal->sps->pic_order_cnt_type == 0
 18.1479 +        && (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb
 18.1480 +            || nal->slc->delta_pic_order_cnt_bottom
 18.1481 +                != last_nal->slc->delta_pic_order_cnt_bottom))) {
 18.1482 +      ret = 1;
 18.1483 +      reason++;
 18.1484 +      /*printf("C: Reason: %d, %d, %d\n", res, nal->slc->pic_order_cnt_lsb,
 18.1485 +          last_nal->slc->pic_order_cnt_lsb);*/
 18.1486 +    }
 18.1487 +    if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1
 18.1488 +        && last_nal->sps->pic_order_cnt_type == 1
 18.1489 +        && (nal->slc->delta_pic_order_cnt[0]
 18.1490 +            != last_nal->slc->delta_pic_order_cnt[0]
 18.1491 +            || nal->slc->delta_pic_order_cnt[1]
 18.1492 +                != last_nal->slc->delta_pic_order_cnt[1]))) {
 18.1493 +      ret = 1;
 18.1494 +      reason++;
 18.1495 +    }
 18.1496 +    if (nal->nal_unit_type != last_nal->nal_unit_type && (nal->nal_unit_type
 18.1497 +        == 5 || last_nal->nal_unit_type == 5)) {
 18.1498 +      ret = 1;
 18.1499 +      reason++;
 18.1500 +    }
 18.1501 +    if (nal->slc && last_nal->slc && (nal->nal_unit_type == 5
 18.1502 +        && last_nal->nal_unit_type == 5 && nal->slc->idr_pic_id
 18.1503 +        != last_nal->slc->idr_pic_id)) {
 18.1504 +      ret = 1;
 18.1505 +      reason++;
 18.1506 +    }
 18.1507 +
 18.1508 +    if (parser->current_nal == parser->nal0) {
 18.1509 +      parser->current_nal = parser->nal1;
 18.1510 +      parser->last_nal = parser->nal0;
 18.1511 +    }
 18.1512 +    else {
 18.1513 +      parser->current_nal = parser->nal0;
 18.1514 +      parser->last_nal = parser->nal1;
 18.1515 +    }
 18.1516 +
 18.1517 +    if(!parser->current_nal->sps && parser->last_nal->sps) {
 18.1518 +      parser->current_nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp));
 18.1519 +      xine_fast_memcpy(parser->current_nal->sps, parser->last_nal->sps, sizeof(struct seq_parameter_set_rbsp));
 18.1520 +    }
 18.1521 +
 18.1522 +    if(!parser->current_nal->pps && parser->last_nal->pps) {
 18.1523 +      parser->current_nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp));
 18.1524 +      xine_fast_memcpy(parser->current_nal->pps, parser->last_nal->pps, sizeof(struct pic_parameter_set_rbsp));
 18.1525 +    }
 18.1526 +
 18.1527 +    /* increase the slice_cnt until a new frame is detected */
 18.1528 +    if (!ret)
 18.1529 +      parser->slice_cnt++;
 18.1530 +
 18.1531 +    return ret;
 18.1532 +  } else if (res == NAL_PPS || res == NAL_SPS) {
 18.1533 +    return 2;
 18.1534 +  } else if (res == NAL_END_OF_SEQUENCE) {
 18.1535 +    if (parser->current_nal == parser->nal0) {
 18.1536 +      parser->current_nal = parser->nal1;
 18.1537 +      parser->last_nal = parser->nal0;
 18.1538 +    }
 18.1539 +    else {
 18.1540 +      parser->current_nal = parser->nal0;
 18.1541 +      parser->last_nal = parser->nal1;
 18.1542 +    }
 18.1543 +
 18.1544 +    return 3;
 18.1545 +  } else if (res >= NAL_SEI) {
 18.1546 +    return 2;
 18.1547 +  }
 18.1548 +
 18.1549 +  return 0;
 18.1550 +}
 18.1551 +
 18.1552 +int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser)
 18.1553 +{
 18.1554 +  if(buf_len <= 0)
 18.1555 +    return -1;
 18.1556 +
 18.1557 +  if(parser->nal_size_length > 0) {
 18.1558 +    if(buf_len < parser->nal_size_length) {
 18.1559 +      return -1;
 18.1560 +    }
 18.1561 +
 18.1562 +    uint32_t next_nal = parser->next_nal_position;
 18.1563 +    if(!next_nal) {
 18.1564 +      struct buf_reader bufr;
 18.1565 +
 18.1566 +      bufr.buf = buf;
 18.1567 +      bufr.cur_pos = buf;
 18.1568 +      bufr.cur_offset = 8;
 18.1569 +      bufr.len = buf_len;
 18.1570 +
 18.1571 +      next_nal = read_bits(&bufr, parser->nal_size_length*8)+parser->nal_size_length;
 18.1572 +    }
 18.1573 +
 18.1574 +    if(next_nal > buf_len) {
 18.1575 +      parser->next_nal_position = next_nal;
 18.1576 +      return -1;
 18.1577 +    } else
 18.1578 +      parser->next_nal_position = 0;
 18.1579 +
 18.1580 +    return next_nal;
 18.1581 +  }
 18.1582 +
 18.1583 +  /* NAL_END_OF_SEQUENCE has only 1 byte, so
 18.1584 +   * we do not need to search for the next start sequence */
 18.1585 +  if(buf[0] == NAL_END_OF_SEQUENCE)
 18.1586 +    return 1;
 18.1587 +
 18.1588 +  int i;
 18.1589 +  for (i = 0; i < buf_len - 2; i++) {
 18.1590 +    if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x01) {
 18.1591 +      //printf("found nal at: %d\n", i);
 18.1592 +      return i;
 18.1593 +    }
 18.1594 +  }
 18.1595 +
 18.1596 +  return -1;
 18.1597 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/video_dec/libvdpau/h264_parser.h	Fri Nov 20 03:46:10 2009 +0000
    19.3 @@ -0,0 +1,98 @@
    19.4 +/*
    19.5 + * Copyright (C) 2008 Julian Scheel
    19.6 + *
    19.7 + * This file is part of xine, a free video player.
    19.8 + *
    19.9 + * xine is free software; you can redistribute it and/or modify
   19.10 + * it under the terms of the GNU General Public License as published by
   19.11 + * the Free Software Foundation; either version 2 of the License, or
   19.12 + * (at your option) any later version.
   19.13 + *
   19.14 + * xine is distributed in the hope that it will be useful,
   19.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   19.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19.17 + * GNU General Public License for more details.
   19.18 + *
   19.19 + * You should have received a copy of the GNU General Public License
   19.20 + * along with this program; if not, write to the Free Software
   19.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   19.22 + *
   19.23 + * h264_parser.h: Almost full-features H264 NAL-Parser
   19.24 + */
   19.25 +
   19.26 +#ifndef NAL_PARSER_H_
   19.27 +#define NAL_PARSER_H_
   19.28 +
   19.29 +#include <stdlib.h>
   19.30 +
   19.31 +#include <xine/xine_internal.h>
   19.32 +#include "nal.h"
   19.33 +#include "dpb.h"
   19.34 +
   19.35 +#define MAX_FRAME_SIZE  1024*1024
   19.36 +
   19.37 +struct nal_parser {
   19.38 +    uint8_t buf[MAX_FRAME_SIZE];
   19.39 +    uint32_t buf_len;
   19.40 +
   19.41 +    /* prebuf is used to store the currently
   19.42 +     * processed nal unit */
   19.43 +    uint8_t prebuf[MAX_FRAME_SIZE];
   19.44 +    uint32_t prebuf_len;
   19.45 +    uint32_t next_nal_position;
   19.46 +    uint8_t incomplete_nal;
   19.47 +
   19.48 +    uint8_t found_sps;
   19.49 +    uint8_t found_pps;
   19.50 +    uint8_t last_nal_res;
   19.51 +
   19.52 +    uint8_t is_idr;
   19.53 +
   19.54 +    int field; /* 0=top, 1=bottom, -1=both */
   19.55 +    int slice;
   19.56 +    int slice_cnt;
   19.57 +
   19.58 +    uint8_t have_top;
   19.59 +    uint8_t have_frame;
   19.60 +
   19.61 +    uint8_t nal_size_length;
   19.62 +    uint32_t next_nal_size;
   19.63 +    uint8_t *nal_size_length_buf;
   19.64 +    uint8_t have_nal_size_length_buf;
   19.65 +
   19.66 +    struct nal_unit *nal0;
   19.67 +    struct nal_unit *nal1;
   19.68 +    struct nal_unit *current_nal;
   19.69 +    struct nal_unit *last_nal;
   19.70 +
   19.71 +    uint8_t cpb_dpb_delays_present_flag;
   19.72 +
   19.73 +    uint32_t pic_order_cnt_lsb;
   19.74 +    uint32_t pic_order_cnt_msb;
   19.75 +    uint32_t prev_pic_order_cnt_lsb;
   19.76 +    uint32_t prev_pic_order_cnt_msb;
   19.77 +    uint32_t frame_num_offset;
   19.78 +
   19.79 +    /* this is dpb used for reference frame
   19.80 +     * heading to vdpau + unordered frames
   19.81 +     */
   19.82 +    struct dpb dpb;
   19.83 +};
   19.84 +
   19.85 +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser);
   19.86 +
   19.87 +int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser);
   19.88 +
   19.89 +struct nal_parser* init_parser();
   19.90 +void free_parser(struct nal_parser *parser);
   19.91 +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
   19.92 +                uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt);
   19.93 +
   19.94 +/* this has to be called after decoding the frame delivered by parse_frame,
   19.95 + * but before adding a decoded frame to the dpb.
   19.96 + */
   19.97 +void process_mmc_operations(struct nal_parser *parser);
   19.98 +
   19.99 +void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len);
  19.100 +
  19.101 +#endif
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/video_dec/libvdpau/nal.c	Fri Nov 20 03:46:10 2009 +0000
    20.3 @@ -0,0 +1,75 @@
    20.4 +/*
    20.5 + * Copyright (C) 2008 Julian Scheel
    20.6 + *
    20.7 + * This file is part of xine, a free video player.
    20.8 + *
    20.9 + * xine is free software; you can redistribute it and/or modify
   20.10 + * it under the terms of the GNU General Public License as published by
   20.11 + * the Free Software Foundation; either version 2 of the License, or
   20.12 + * (at your option) any later version.
   20.13 + *
   20.14 + * xine is distributed in the hope that it will be useful,
   20.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.17 + * GNU General Public License for more details.
   20.18 + *
   20.19 + * You should have received a copy of the GNU General Public License
   20.20 + * along with this program; if not, write to the Free Software
   20.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   20.22 + *
   20.23 + * nal.c: nal-structure utility functions
   20.24 + */
   20.25 +
   20.26 +#include <stdio.h>
   20.27 +#include <stdlib.h>
   20.28 +#include <string.h>
   20.29 +
   20.30 +#include "nal.h"
   20.31 +#include <xine/xine_internal.h>
   20.32 +
   20.33 +struct nal_unit* init_nal_unit()
   20.34 +{
   20.35 +  struct nal_unit *nal = calloc(1, sizeof(struct nal_unit));
   20.36 +
   20.37 +  /*nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp));
   20.38 +  nal->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp));
   20.39 +  nal->slc = calloc(1, sizeof(struct slice_header));*/
   20.40 +
   20.41 +  return nal;
   20.42 +}
   20.43 +
   20.44 +void free_nal_unit(struct nal_unit *nal)
   20.45 +{
   20.46 +  if(!nal)
   20.47 +    return;
   20.48 +
   20.49 +  free(nal->sps);
   20.50 +  free(nal->pps);
   20.51 +  free(nal->slc);
   20.52 +  free(nal);
   20.53 +}
   20.54 +
   20.55 +void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src)
   20.56 +{
   20.57 +  /* size without pps, sps and slc units: */
   20.58 +  int size = sizeof(struct nal_unit) - sizeof(struct seq_parameter_set_rbsp*)
   20.59 +      - sizeof(struct pic_parameter_set_rbsp*) - sizeof(struct slice_header*);
   20.60 +
   20.61 +  xine_fast_memcpy(dest, src, size);
   20.62 +
   20.63 +  if(!dest->sps)
   20.64 +    dest->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp));
   20.65 +
   20.66 +  if(!dest->pps)
   20.67 +    dest->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp));
   20.68 +
   20.69 +  if(!dest->slc)
   20.70 +    dest->slc = calloc(1, sizeof(struct slice_header));
   20.71 +
   20.72 +  if(src->sps)
   20.73 +    xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp));
   20.74 +  if(src->pps)
   20.75 +    xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp));
   20.76 +  if(src->slc)
   20.77 +    xine_fast_memcpy(dest->slc, src->slc, sizeof(struct slice_header));
   20.78 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/video_dec/libvdpau/nal.h	Fri Nov 20 03:46:10 2009 +0000
    21.3 @@ -0,0 +1,466 @@
    21.4 +/*
    21.5 + * Copyright (C) 2008 Julian Scheel
    21.6 + *
    21.7 + * This file is part of xine, a free video player.
    21.8 + *
    21.9 + * xine is free software; you can redistribute it and/or modify
   21.10 + * it under the terms of the GNU General Public License as published by
   21.11 + * the Free Software Foundation; either version 2 of the License, or
   21.12 + * (at your option) any later version.
   21.13 + *
   21.14 + * xine is distributed in the hope that it will be useful,
   21.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.17 + * GNU General Public License for more details.
   21.18 + *
   21.19 + * You should have received a copy of the GNU General Public License
   21.20 + * along with this program; if not, write to the Free Software
   21.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   21.22 + *
   21.23 + * nal.h: H264 NAL structures
   21.24 + */
   21.25 +
   21.26 +#ifndef NAL_H_
   21.27 +#define NAL_H_
   21.28 +#include <stdint.h>
   21.29 +#include <vdpau/vdpau.h>
   21.30 +
   21.31 +enum nal_unit_types
   21.32 +{
   21.33 +  NAL_UNSPECIFIED = 0,
   21.34 +  NAL_SLICE,
   21.35 +  NAL_PART_A,
   21.36 +  NAL_PART_B,
   21.37 +  NAL_PART_C,
   21.38 +  NAL_SLICE_IDR,
   21.39 +  NAL_SEI,
   21.40 +  NAL_SPS,
   21.41 +  NAL_PPS,
   21.42 +  NAL_AU_DELIMITER,
   21.43 +  NAL_END_OF_SEQUENCE,
   21.44 +  NAL_END_OF_STREAM,
   21.45 +  NAL_FILLER_DATA,
   21.46 +  NAL_SPS_EXT
   21.47 +};
   21.48 +
   21.49 +enum pic_struct {
   21.50 +  DISP_FRAME = 0,
   21.51 +  DISP_TOP,
   21.52 +  DISP_BOTTOM,
   21.53 +  DISP_TOP_BOTTOM,
   21.54 +  DISP_BOTTOM_TOP,
   21.55 +  DISP_TOP_BOTTOM_TOP,
   21.56 +  DISP_TOP_TOP_BOTTOM,
   21.57 +  DISP_BOTTOM_TOP_BOTTOM,
   21.58 +  DISP_FRAME_DOUBLING,
   21.59 +  DISP_FRAME_TRIPLING
   21.60 +};
   21.61 +
   21.62 +/* slice types repeat from 5-9, we
   21.63 + * need a helper function for comparison
   21.64 + */
   21.65 +enum slice_types
   21.66 +{
   21.67 +  SLICE_P = 0, SLICE_B, SLICE_I, SLICE_SP, SLICE_SI
   21.68 +};
   21.69 +
   21.70 +enum aspect_ratio
   21.71 +{
   21.72 +  ASPECT_UNSPECIFIED = 0,
   21.73 +  ASPECT_1_1,
   21.74 +  ASPECT_12_11,
   21.75 +  ASPECT_10_11,
   21.76 +  ASPECT_16_11,
   21.77 +  ASPECT_40_33,
   21.78 +  ASPECT_24_11,
   21.79 +  ASPECT_20_11,
   21.80 +  ASPECT_32_11,
   21.81 +  ASPECT_80_33,
   21.82 +  ASPECT_18_11,
   21.83 +  ASPECT_15_11,
   21.84 +  ASPECT_64_33,
   21.85 +  ASPECT_160_99,
   21.86 +  ASPECT_4_3,
   21.87 +  ASPECT_3_2,
   21.88 +  ASPECT_2_1,
   21.89 +  ASPECT_RESERVED,
   21.90 +  ASPECT_EXTENDED_SAR=255
   21.91 +};
   21.92 +
   21.93 +static const uint8_t zigzag_4x4[16] = {
   21.94 +  0+0*4, 1+0*4, 0+1*4, 0+2*4,
   21.95 +  1+1*4, 2+0*4, 3+0*4, 2+1*4,
   21.96 +  1+2*4, 0+3*4, 1+3*4, 2+2*4,
   21.97 +  3+1*4, 3+2*4, 2+3*4, 3+3*4,
   21.98 +};
   21.99 +
  21.100 +static const uint8_t zigzag_8x8[64] = {
  21.101 +  0+0*8, 1+0*8, 0+1*8, 0+2*8,
  21.102 +  1+1*8, 2+0*8, 3+0*8, 2+1*8,
  21.103 +  1+2*8, 0+3*8, 0+4*8, 1+3*8,
  21.104 +  2+2*8, 3+1*8, 4+0*8, 5+0*8,
  21.105 +  4+1*8, 3+2*8, 2+3*8, 1+4*8,
  21.106 +  0+5*8, 0+6*8, 1+5*8, 2+4*8,
  21.107 +  3+3*8, 4+2*8, 5+1*8, 6+0*8,
  21.108 +  7+0*8, 6+1*8, 5+2*8, 4+3*8,
  21.109 +  3+4*8, 2+5*8, 1+6*8, 0+7*8,
  21.110 +  1+7*8, 2+6*8, 3+5*8, 4+4*8,
  21.111 +  5+3*8, 6+2*8, 7+1*8, 7+2*8,
  21.112 +  6+3*8, 5+4*8, 4+5*8, 3+6*8,
  21.113 +  2+7*8, 3+7*8, 4+6*8, 5+5*8,
  21.114 +  6+4*8, 7+3*8, 7+4*8, 6+5*8,
  21.115 +  5+6*8, 4+7*8, 5+7*8, 6+6*8,
  21.116 +  7+5*8, 7+6*8, 6+7*8, 7+7*8,
  21.117 +};
  21.118 +
  21.119 +static inline uint32_t slice_type(uint32_t slice_type)
  21.120 +{
  21.121 +  return (slice_type < 10 ? slice_type % 5 : slice_type);
  21.122 +}
  21.123 +
  21.124 +static inline void print_slice_type(uint32_t slice_type)
  21.125 +{
  21.126 +  switch(slice_type) {
  21.127 +    case SLICE_P:
  21.128 +      printf("SLICE_P\n");
  21.129 +      break;
  21.130 +    case SLICE_B:
  21.131 +      printf("SLICE_B\n");
  21.132 +      break;
  21.133 +    case SLICE_I:
  21.134 +      printf("SLICE_I\n");
  21.135 +      break;
  21.136 +    case SLICE_SP:
  21.137 +      printf("SLICE_SP\n");
  21.138 +      break;
  21.139 +    case SLICE_SI:
  21.140 +      printf("SLICE_SI\n");
  21.141 +      break;
  21.142 +    default:
  21.143 +      printf("Unknown SLICE\n");
  21.144 +  }
  21.145 +}
  21.146 +
  21.147 +struct hrd_parameters
  21.148 +{
  21.149 +  uint32_t cpb_cnt_minus1;
  21.150 +  uint8_t bit_rate_scale;
  21.151 +  uint8_t cpb_size_scale;
  21.152 +
  21.153 +  uint32_t bit_rate_value_minus1[32];
  21.154 +  uint32_t cpb_size_value_minus1[32];
  21.155 +  uint8_t cbr_flag[32];
  21.156 +
  21.157 +  uint8_t initial_cpb_removal_delay_length_minus1;
  21.158 +  uint8_t cpb_removal_delay_length_minus1;
  21.159 +  uint8_t dpb_output_delay_length_minus1;
  21.160 +  uint8_t time_offset_length;
  21.161 +};
  21.162 +
  21.163 +struct seq_parameter_set_rbsp
  21.164 +{
  21.165 +  uint8_t profile_idc; // 0xff
  21.166 +  uint8_t constraint_setN_flag; // 0x0f
  21.167 +  uint8_t level_idc; // 0xff
  21.168 +  uint32_t seq_parameter_set_id;
  21.169 +  uint32_t chroma_format_idc;
  21.170 +  uint8_t separate_colour_plane_flag; // 0x01
  21.171 +  uint32_t bit_depth_luma_minus8;
  21.172 +  uint32_t bit_depth_chroma_minus8;
  21.173 +  uint8_t qpprime_y_zero_transform_bypass_flag;
  21.174 +  uint8_t seq_scaling_matrix_present_flag;
  21.175 +
  21.176 +  /* if(seq_scaling_matrix_present_flag) */
  21.177 +  uint8_t seq_scaling_list_present_flag[8];
  21.178 +
  21.179 +  uint8_t scaling_lists_4x4[6][16];
  21.180 +  uint8_t scaling_lists_8x8[2][64];
  21.181 +  /* endif */
  21.182 +
  21.183 +  uint32_t log2_max_frame_num_minus4;
  21.184 +  uint32_t pic_order_cnt_type;
  21.185 +  // if pic_order_cnt_type==0
  21.186 +  uint32_t log2_max_pic_order_cnt_lsb_minus4;
  21.187 +  // else
  21.188 +  uint8_t delta_pic_order_always_zero_flag;
  21.189 +  int32_t offset_for_non_ref_pic;
  21.190 +  int32_t offset_for_top_to_bottom_field;
  21.191 +  uint8_t num_ref_frames_in_pic_order_cnt_cycle;
  21.192 +  int32_t offset_for_ref_frame[256];
  21.193 +  // TODO: some more ignored here
  21.194 +  uint32_t num_ref_frames;
  21.195 +  uint8_t gaps_in_frame_num_value_allowed_flag;
  21.196 +  /*uint32_t    pic_width_in_mbs_minus1;
  21.197 +   uint32_t    pic_height_in_map_units_minus1;*/
  21.198 +  uint32_t pic_width;
  21.199 +  uint32_t pic_height;
  21.200 +  uint8_t frame_mbs_only_flag;
  21.201 +  uint8_t mb_adaptive_frame_field_flag;
  21.202 +  uint8_t direct_8x8_inference_flag;
  21.203 +  uint8_t frame_cropping_flag;
  21.204 +  uint32_t frame_crop_left_offset;
  21.205 +  uint32_t frame_crop_right_offset;
  21.206 +  uint32_t frame_crop_top_offset;
  21.207 +  uint32_t frame_crop_bottom_offset;
  21.208 +  uint8_t vui_parameters_present_flag;
  21.209 +
  21.210 +  /* vui_parameters */
  21.211 +  struct
  21.212 +  {
  21.213 +    uint8_t aspect_ration_info_present_flag;
  21.214 +
  21.215 +    /* aspect_ration_info_present_flag == 1 */
  21.216 +    uint8_t aspect_ratio_idc;
  21.217 +    uint16_t sar_width;
  21.218 +    uint16_t sar_height;
  21.219 +
  21.220 +    uint8_t overscan_info_present_flag;
  21.221 +    /* overscan_info_present_flag == 1 */
  21.222 +    uint8_t overscan_appropriate_flag;
  21.223 +
  21.224 +    uint8_t video_signal_type_present_flag;
  21.225 +    /* video_signal_type_present_flag == 1 */
  21.226 +    uint8_t video_format;
  21.227 +    uint8_t video_full_range_flag;
  21.228 +    uint8_t colour_description_present;
  21.229 +    /* colour_description_present == 1 */
  21.230 +    uint8_t colour_primaries;
  21.231 +    uint8_t transfer_characteristics;
  21.232 +    uint8_t matrix_coefficients;
  21.233 +
  21.234 +    uint8_t chroma_loc_info_present_flag;
  21.235 +    /* chroma_loc_info_present_flag == 1 */
  21.236 +    uint8_t chroma_sample_loc_type_top_field;
  21.237 +    uint8_t chroma_sample_loc_type_bottom_field;
  21.238 +
  21.239 +    uint8_t timing_info_present_flag;
  21.240 +    /* timing_info_present_flag == 1 */
  21.241 +    uint32_t num_units_in_tick;
  21.242 +    uint32_t time_scale;
  21.243 +    uint8_t fixed_frame_rate_flag;
  21.244 +
  21.245 +    uint8_t nal_hrd_parameters_present_flag;
  21.246 +    struct hrd_parameters nal_hrd_parameters;
  21.247 +
  21.248 +    uint8_t vc1_hrd_parameters_present_flag;
  21.249 +    struct hrd_parameters vc1_hrd_parameters;
  21.250 +
  21.251 +    uint8_t low_delay_hrd_flag;
  21.252 +
  21.253 +    uint8_t pic_struct_present_flag;
  21.254 +    uint8_t bitstream_restriction_flag;
  21.255 +
  21.256 +    /* bitstream_restriction_flag == 1 */
  21.257 +    uint8_t motion_vectors_over_pic_boundaries;
  21.258 +    uint32_t max_bytes_per_pic_denom;
  21.259 +    uint32_t max_bits_per_mb_denom;
  21.260 +    uint32_t log2_max_mv_length_horizontal;
  21.261 +    uint32_t log2_max_mv_length_vertical;
  21.262 +    uint32_t num_reorder_frames;
  21.263 +    uint32_t max_dec_frame_buffering;
  21.264 +  } vui_parameters;
  21.265 +
  21.266 +};
  21.267 +
  21.268 +struct pic_parameter_set_rbsp
  21.269 +{
  21.270 +  uint32_t pic_parameter_set_id;
  21.271 +  uint32_t seq_parameter_set_id;
  21.272 +  uint8_t entropy_coding_mode_flag;
  21.273 +  uint8_t pic_order_present_flag;
  21.274 +
  21.275 +  uint32_t num_slice_groups_minus1;
  21.276 +
  21.277 +  /* num_slice_groups_minus1 > 0 */
  21.278 +  uint32_t slice_group_map_type;
  21.279 +
  21.280 +  /* slice_group_map_type == 1 */
  21.281 +  uint32_t run_length_minus1[64];
  21.282 +
  21.283 +  /* slice_group_map_type == 2 */
  21.284 +  uint32_t top_left[64];
  21.285 +  uint32_t bottom_right[64];
  21.286 +
  21.287 +  /* slice_group_map_type == 3,4,5 */
  21.288 +  uint8_t slice_group_change_direction_flag;
  21.289 +  uint32_t slice_group_change_rate_minus1;
  21.290 +
  21.291 +  /* slice_group_map_type == 6 */
  21.292 +  uint32_t pic_size_in_map_units_minus1;
  21.293 +  uint8_t slice_group_id[64];
  21.294 +
  21.295 +  uint32_t num_ref_idx_l0_active_minus1;
  21.296 +  uint32_t num_ref_idx_l1_active_minus1;
  21.297 +  uint8_t weighted_pred_flag;
  21.298 +  uint8_t weighted_bipred_idc;
  21.299 +  int32_t pic_init_qp_minus26;
  21.300 +  int32_t pic_init_qs_minus26;
  21.301 +  int32_t chroma_qp_index_offset;
  21.302 +  uint8_t deblocking_filter_control_present_flag;
  21.303 +  uint8_t constrained_intra_pred_flag;
  21.304 +  uint8_t redundant_pic_cnt_present_flag;
  21.305 +
  21.306 +  /* if(more_rbsp_data) */
  21.307 +  uint8_t transform_8x8_mode_flag;
  21.308 +  uint8_t pic_scaling_matrix_present_flag;
  21.309 +
  21.310 +  /* if(pic_scaling_matrix_present_flag) */
  21.311 +  uint8_t pic_scaling_list_present_flag[8];
  21.312 +
  21.313 +  uint8_t scaling_lists_4x4[6][16];
  21.314 +  uint8_t scaling_lists_8x8[2][64];
  21.315 +
  21.316 +  int32_t second_chroma_qp_index_offset;
  21.317 +};
  21.318 +
  21.319 +/*struct clock_timestamp {
  21.320 +  uint8_t ct_type;
  21.321 +  uint8_t nuit_fiel_based_flag;
  21.322 +  uint8_t counting_type;
  21.323 +  uint8_t full_timestamp_flag;
  21.324 +  uint8_t discontinuity_flag;
  21.325 +  uint8_t cnt_dropped_flag;
  21.326 +  uint8_t n_frames
  21.327 +};*/
  21.328 +
  21.329 +/* sei contains several additional info, we do
  21.330 + * only care for pic_timing, to handle display
  21.331 + * reordering
  21.332 + */
  21.333 +struct sei_message
  21.334 +{
  21.335 +  uint32_t payload_type;
  21.336 +  uint8_t last_payload_type_byte;
  21.337 +  uint32_t payload_size;
  21.338 +  uint8_t last_payload_size_byte;
  21.339 +
  21.340 +  struct
  21.341 +  {
  21.342 +    /* cpb_dpb_delays_present_flag == 1 */
  21.343 +    uint8_t cpb_removal_delay;
  21.344 +    uint8_t dpb_output_delay;
  21.345 +
  21.346 +    uint8_t pic_struct;
  21.347 +    //uint8_t clock_timestamp_flag[3];
  21.348 +  } pic_timing;
  21.349 +};
  21.350 +
  21.351 +struct slice_header
  21.352 +{
  21.353 +  uint32_t first_mb_in_slice;
  21.354 +  uint32_t slice_type;
  21.355 +  uint32_t pic_parameter_set_id;
  21.356 +  uint8_t colour_plane_id;
  21.357 +  uint32_t frame_num;
  21.358 +  uint8_t field_pic_flag;
  21.359 +  uint8_t bottom_field_flag;
  21.360 +  uint32_t idr_pic_id;
  21.361 +
  21.362 +  /* sps->pic_order_cnt_type == 0 */
  21.363 +  uint32_t pic_order_cnt_lsb;
  21.364 +  int32_t delta_pic_order_cnt_bottom;
  21.365 +  /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */
  21.366 +  int32_t delta_pic_order_cnt[2];
  21.367 +
  21.368 +  /* pps->redundant_pic_cnt_present_flag == 1 */
  21.369 +  int32_t redundant_pic_cnt;
  21.370 +
  21.371 +  /* slice_type == B */
  21.372 +  uint8_t direct_spatial_mv_pred_flag;
  21.373 +
  21.374 +  /* slice_type == P, SP, B */
  21.375 +  uint8_t num_ref_idx_active_override_flag;
  21.376 +  /* num_ref_idx_active_override_flag == 1 */
  21.377 +  uint32_t num_ref_idx_l0_active_minus1;
  21.378 +  /* slice type == B */
  21.379 +  uint32_t num_ref_idx_l1_active_minus1;
  21.380 +
  21.381 +  /* ref_pic_list_reordering */
  21.382 +  struct
  21.383 +  {
  21.384 +    /* slice_type != I && slice_type != SI */
  21.385 +    uint8_t ref_pic_list_reordering_flag_l0;
  21.386 +
  21.387 +    /* slice_type == B */
  21.388 +    uint8_t ref_pic_list_reordering_flag_l1;
  21.389 +
  21.390 +    /* ref_pic_list_reordering_flag_l0 == 1 */
  21.391 +    uint32_t reordering_of_pic_nums_idc;
  21.392 +
  21.393 +    /* reordering_of_pic_nums_idc == 0, 1 */
  21.394 +    uint32_t abs_diff_pic_num_minus1;
  21.395 +
  21.396 +    /* reordering_of_pic_nums_idc == 2) */
  21.397 +    uint32_t long_term_pic_num;
  21.398 +  } ref_pic_list_reordering;
  21.399 +
  21.400 +  /* pred_weight_table */
  21.401 +  struct
  21.402 +  {
  21.403 +    uint32_t luma_log2_weight_denom;
  21.404 +
  21.405 +    /* chroma_format_idc != 0 */
  21.406 +    uint32_t chroma_log2_weight_denom;
  21.407 +
  21.408 +    int32_t luma_weight_l0[32];
  21.409 +    int32_t luma_offset_l0[32];
  21.410 +
  21.411 +    int32_t chroma_weight_l0[32][2];
  21.412 +    int32_t chroma_offset_l0[32][2];
  21.413 +
  21.414 +    int32_t luma_weight_l1[32];
  21.415 +    int32_t luma_offset_l1[32];
  21.416 +
  21.417 +    int32_t chroma_weight_l1[32][2];
  21.418 +    int32_t chroma_offset_l1[32][2];
  21.419 +  } pred_weight_table;
  21.420 +
  21.421 +  /* def_rec_pic_marking */
  21.422 +  struct
  21.423 +  {
  21.424 +
  21.425 +    /* nal_unit_type == NAL_SLICE_IDR */
  21.426 +    uint8_t no_output_of_prior_pics_flag;
  21.427 +    uint8_t long_term_reference_flag;
  21.428 +
  21.429 +    /* else */
  21.430 +    uint8_t adaptive_ref_pic_marking_mode_flag;
  21.431 +    uint32_t memory_management_control_operation;
  21.432 +
  21.433 +    uint32_t difference_of_pic_nums_minus1;
  21.434 +    uint32_t long_term_pic_num;
  21.435 +    uint32_t long_term_frame_idx;
  21.436 +    uint32_t max_long_term_frame_idx_plus1;
  21.437 +  } dec_ref_pic_marking[10];
  21.438 +  uint32_t dec_ref_pic_marking_count;
  21.439 +};
  21.440 +
  21.441 +struct nal_unit
  21.442 +{
  21.443 +  uint8_t nal_ref_idc; // 0x03
  21.444 +  uint8_t nal_unit_type; // 0x1f
  21.445 +
  21.446 +  uint32_t max_pic_num;
  21.447 +  uint32_t curr_pic_num;
  21.448 +  uint8_t used_for_long_term_ref;
  21.449 +  uint32_t long_term_pic_num;
  21.450 +  uint32_t long_term_frame_idx;
  21.451 +
  21.452 +  int32_t top_field_order_cnt;
  21.453 +  int32_t bottom_field_order_cnt;
  21.454 +
  21.455 +  uint8_t interlaced;
  21.456 +  uint8_t repeat_pic;
  21.457 +
  21.458 +  struct sei_message sei;
  21.459 +
  21.460 +  struct seq_parameter_set_rbsp *sps;
  21.461 +  struct pic_parameter_set_rbsp *pps;
  21.462 +  struct slice_header *slc;
  21.463 +};
  21.464 +
  21.465 +struct nal_unit* init_nal_unit();
  21.466 +void free_nal_unit(struct nal_unit *nal);
  21.467 +void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src);
  21.468 +
  21.469 +#endif /* NAL_H_ */
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/src/video_dec/libvdpau/vdpau_h264.c	Fri Nov 20 03:46:10 2009 +0000
    22.3 @@ -0,0 +1,869 @@
    22.4 +/*
    22.5 + * Copyright (C) 2008 Julian Scheel
    22.6 + *
    22.7 + * This file is part of xine, a free video player.
    22.8 + *
    22.9 + * xine is free software; you can redistribute it and/or modify
   22.10 + * it under the terms of the GNU General Public License as published by
   22.11 + * the Free Software Foundation; either version 2 of the License, or
   22.12 + * (at your option) any later version.
   22.13 + *
   22.14 + * xine is distributed in the hope that it will be useful,
   22.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.17 + * GNU General Public License for more details.
   22.18 + *
   22.19 + * You should have received a copy of the GNU General Public License
   22.20 + * along with this program; if not, write to the Free Software
   22.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   22.22 + *
   22.23 + * vdpau_h264.c: H264 Video Decoder utilizing nvidia VDPAU engine
   22.24 + */
   22.25 +
   22.26 +#include <stdio.h>
   22.27 +#include <stdlib.h>
   22.28 +#include <string.h>
   22.29 +#include <sys/types.h>
   22.30 +#include <unistd.h>
   22.31 +#include <vdpau/vdpau.h>
   22.32 +
   22.33 +#include <xine/xine_internal.h>
   22.34 +#include <xine/video_out.h>
   22.35 +#include <xine/buffer.h>
   22.36 +#include <xine/xineutils.h>
   22.37 +#include "bswap.h"
   22.38 +#include "accel_vdpau.h"
   22.39 +#include "h264_parser.h"
   22.40 +#include "dpb.h"
   22.41 +
   22.42 +#define VIDEOBUFSIZE 128*1024
   22.43 +
   22.44 +typedef struct {
   22.45 +  video_decoder_class_t   decoder_class;
   22.46 +} vdpau_h264_class_t;
   22.47 +
   22.48 +typedef struct vdpau_h264_decoder_s {
   22.49 +  video_decoder_t   video_decoder;  /* parent video decoder structure */
   22.50 +
   22.51 +  vdpau_h264_class_t *class;
   22.52 +  xine_stream_t    *stream;
   22.53 +
   22.54 +  /* these are traditional variables in a video decoder object */
   22.55 +  uint64_t          video_step;  /* frame duration in pts units */
   22.56 +
   22.57 +  int               width;       /* the width of a video frame */
   22.58 +  int               height;      /* the height of a video frame */
   22.59 +  double            ratio;       /* the width to height ratio */
   22.60 +
   22.61 +
   22.62 +  struct nal_parser *nal_parser;  /* h264 nal parser. extracts stream data for vdpau */
   22.63 +  uint8_t           wait_for_bottom_field;
   22.64 +  struct decoded_picture *last_ref_pic;
   22.65 +  uint32_t          last_top_field_order_cnt;
   22.66 +
   22.67 +  int               have_frame_boundary_marks;
   22.68 +  int               wait_for_frame_start;
   22.69 +
   22.70 +  VdpDecoder        decoder;
   22.71 +  int               decoder_started;
   22.72 +
   22.73 +  VdpColorStandard  color_standard;
   22.74 +  VdpDecoderProfile profile;
   22.75 +  vdpau_accel_t     *vdpau_accel;
   22.76 +
   22.77 +  xine_t            *xine;
   22.78 +
   22.79 +  int64_t           curr_pts;
   22.80 +  int64_t           next_pts;
   22.81 +
   22.82 +  vo_frame_t        *last_img;
   22.83 +  vo_frame_t        *dangling_img;
   22.84 +
   22.85 +  uint8_t           *codec_private;
   22.86 +  uint32_t          codec_private_len;
   22.87 +
   22.88 +  int               vdp_runtime_nr;
   22.89 +
   22.90 +} vdpau_h264_decoder_t;
   22.91 +
   22.92 +static void vdpau_h264_reset (video_decoder_t *this_gen);
   22.93 +static void vdpau_h264_flush (video_decoder_t *this_gen);
   22.94 +
   22.95 +/**************************************************************************
   22.96 + * vdpau_h264 specific decode functions
   22.97 + *************************************************************************/
   22.98 +
   22.99 +/**************************************************************************
  22.100 + * xine video plugin functions
  22.101 + *************************************************************************/
  22.102 +
  22.103 +
  22.104 +static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic)
  22.105 +{
  22.106 +  printf("C: slice_count: %d\n", pic->slice_count);
  22.107 +  printf("C: field_order_cnt[0]: %d\n", pic->field_order_cnt[0]);
  22.108 +  printf("C: field_order_cnt[1]: %d\n", pic->field_order_cnt[1]);
  22.109 +  printf("C: is_reference: %d\n", pic->is_reference);
  22.110 +  printf("C: frame_num: %d\n", pic->frame_num);
  22.111 +  printf("C: field_pic_flag: %d\n", pic->field_pic_flag);
  22.112 +  printf("C: bottom_field_flag: %d\n", pic->bottom_field_flag);
  22.113 +  printf("C: num_ref_frames: %d\n", pic->num_ref_frames);
  22.114 +  printf("C: mb_adaptive_frame_field_flag: %d\n", pic->mb_adaptive_frame_field_flag);
  22.115 +  printf("C: constrained_intra_pred_flag: %d\n", pic->constrained_intra_pred_flag);
  22.116 +  printf("C: weighted_pred_flag: %d\n", pic->weighted_pred_flag);
  22.117 +  printf("C: weighted_bipred_idc: %d\n", pic->weighted_bipred_idc);
  22.118 +  printf("C: frame_mbs_only_flag: %d\n", pic->frame_mbs_only_flag);
  22.119 +  printf("C: transform_8x8_mode_flag: %d\n", pic->transform_8x8_mode_flag);
  22.120 +  printf("C: chroma_qp_index_offset: %d\n", pic->chroma_qp_index_offset);
  22.121 +  printf("C: second_chroma_qp_index_offset: %d\n", pic->second_chroma_qp_index_offset);
  22.122 +  printf("C: pic_init_qp_minus26: %d\n", pic->pic_init_qp_minus26);
  22.123 +  printf("C: num_ref_idx_l0_active_minus1: %d\n", pic->num_ref_idx_l0_active_minus1);
  22.124 +  printf("C: num_ref_idx_l1_active_minus1: %d\n", pic->num_ref_idx_l1_active_minus1);
  22.125 +  printf("C: log2_max_frame_num_minus4: %d\n", pic->log2_max_frame_num_minus4);
  22.126 +  printf("C: pic_order_cnt_type: %d\n", pic->pic_order_cnt_type);
  22.127 +  printf("C: log2_max_pic_order_cnt_lsb_minus4: %d\n", pic->log2_max_pic_order_cnt_lsb_minus4);
  22.128 +  printf("C: delta_pic_order_always_zero_flag: %d\n", pic->delta_pic_order_always_zero_flag);
  22.129 +  printf("C: direct_8x8_inference_flag: %d\n", pic->direct_8x8_inference_flag);
  22.130 +  printf("C: entropy_coding_mode_flag: %d\n", pic->entropy_coding_mode_flag);
  22.131 +  printf("C: pic_order_present_flag: %d\n", pic->pic_order_present_flag);
  22.132 +  printf("C: deblocking_filter_control_present_flag: %d\n", pic->deblocking_filter_control_present_flag);
  22.133 +  printf("C: redundant_pic_cnt_present_flag: %d\n", pic->redundant_pic_cnt_present_flag);
  22.134 +
  22.135 +  int i, j;
  22.136 +  for(i = 0; i < 6; i++) {
  22.137 +    printf("C: scalint_list4x4[%d]:\nC:", i);
  22.138 +    for(j = 0; j < 16; j++) {
  22.139 +      printf(" [%d]", pic->scaling_lists_4x4[i][j]);
  22.140 +      if(j%8 == 0)
  22.141 +        printf("\nC:");
  22.142 +    }
  22.143 +    printf("C: \n");
  22.144 +  }
  22.145 +  for(i = 0; i < 2; i++) {
  22.146 +    printf("C: scalint_list8x8[%d]:\nC:", i);
  22.147 +    for(j = 0; j < 64; j++) {
  22.148 +      printf(" [%d] ", pic->scaling_lists_8x8[i][j]);
  22.149 +      if(j%8 == 0)
  22.150 +        printf("\nC:");
  22.151 +    }
  22.152 +    printf("C: \n");
  22.153 +  }
  22.154 +
  22.155 +  //int i;
  22.156 +  for(i = 0; i < 16; i++) {
  22.157 +    if(pic->referenceFrames[i].surface != VDP_INVALID_HANDLE) {
  22.158 +    printf("C: -------------------\n");
  22.159 +      printf("C: Reference Frame %d:\n", i);
  22.160 +    printf("C: frame_idx: %d\n", pic->referenceFrames[i].frame_idx);
  22.161 +    printf("C: field_order_cnt[0]: %d\n", pic->referenceFrames[i].field_order_cnt[0]);
  22.162 +    printf("C: field_order_cnt[1]: %d\n", pic->referenceFrames[i].field_order_cnt[0]);
  22.163 +    printf("C: is_long_term: %d\n", pic->referenceFrames[i].is_long_term);
  22.164 +    printf("C: top_is_reference: %d\n", pic->referenceFrames[i].top_is_reference);
  22.165 +    printf("C: bottom_is_reference: %d\n", pic->referenceFrames[i].bottom_is_reference);
  22.166 +    }
  22.167 +  }
  22.168 +  printf("C: ---------------------------------------------------------------\n");
  22.169 +  /*memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16);
  22.170 +  memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64);
  22.171 +  memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames));*/
  22.172 +
  22.173 +}
  22.174 +
  22.175 +static void set_ratio(video_decoder_t *this_gen)
  22.176 +{
  22.177 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen;
  22.178 +
  22.179 +  this->ratio = (double)this->width / (double)this->height;
  22.180 +  if(this->nal_parser->current_nal->sps->vui_parameters.aspect_ration_info_present_flag) {
  22.181 +    switch(this->nal_parser->current_nal->sps->vui_parameters.aspect_ratio_idc) {
  22.182 +      case ASPECT_1_1:
  22.183 +        this->ratio = 1 * this->ratio;
  22.184 +        break;
  22.185 +      case ASPECT_12_11:
  22.186 +        this->ratio *= 12.0/11.0;
  22.187 +        break;
  22.188 +      case ASPECT_10_11:
  22.189 +        this->ratio *= 10.0/11.0;
  22.190 +        break;
  22.191 +      case ASPECT_16_11:
  22.192 +        this->ratio *= 16.0/11.0;
  22.193 +        break;
  22.194 +      case ASPECT_40_33:
  22.195 +        this->ratio *= 40.0/33.0;
  22.196 +        break;
  22.197 +      case ASPECT_24_11:
  22.198 +        this->ratio *= 24.0/11.0;
  22.199 +        break;
  22.200 +      case ASPECT_20_11:
  22.201 +        this->ratio *= 20.0/11.0;
  22.202 +        break;
  22.203 +      case ASPECT_32_11:
  22.204 +        this->ratio *= 32.0/11.0;
  22.205 +        break;
  22.206 +      case ASPECT_80_33:
  22.207 +        this->ratio *= 80.0/33.0;
  22.208 +        break;
  22.209 +      case ASPECT_18_11:
  22.210 +        this->ratio *= 18.0/11.0;
  22.211 +        break;
  22.212 +      case ASPECT_15_11:
  22.213 +        this->ratio *= 15.0/11.0;
  22.214 +        break;
  22.215 +      case ASPECT_64_33:
  22.216 +        this->ratio *= 64.0/33.0;
  22.217 +        break;
  22.218 +      case ASPECT_160_99:
  22.219 +        this->ratio *= 160.0/99.0;
  22.220 +        break;
  22.221 +      case ASPECT_4_3:
  22.222 +        this->ratio *= 4.0/3.0;
  22.223 +        break;
  22.224 +      case ASPECT_3_2:
  22.225 +        this->ratio *= 3.0/2.0;
  22.226 +        break;
  22.227 +      case ASPECT_2_1:
  22.228 +        this->ratio *= 2.0/1.0;
  22.229 +        break;
  22.230 +      case ASPECT_EXTENDED_SAR:
  22.231 +        this->ratio *=
  22.232 +          (double)this->nal_parser->current_nal->sps->vui_parameters.sar_width/
  22.233 +          (double)this->nal_parser->current_nal->sps->vui_parameters.sar_height;
  22.234 +        break;
  22.235 +    }
  22.236 +  }
  22.237 +}
  22.238 +
  22.239 +static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slice_count, VdpPictureInfoH264 *pic)
  22.240 +{
  22.241 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen;
  22.242 +
  22.243 +  struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps;
  22.244 +  struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps;
  22.245 +  struct slice_header *slc = this->nal_parser->current_nal->slc;
  22.246 +
  22.247 +  pic->slice_count = slice_count;
  22.248 +  pic->field_order_cnt[0] = this->nal_parser->current_nal->top_field_order_cnt;
  22.249 +  pic->field_order_cnt[1] = this->nal_parser->current_nal->bottom_field_order_cnt;
  22.250 +  pic->is_reference =
  22.251 +    (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE;
  22.252 +  pic->frame_num = slc->frame_num;
  22.253 +  pic->field_pic_flag = slc->field_pic_flag;
  22.254 +  pic->bottom_field_flag = slc->bottom_field_flag;
  22.255 +  pic->num_ref_frames = sps->num_ref_frames;
  22.256 +  pic->mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag && !slc->field_pic_flag;
  22.257 +  pic->constrained_intra_pred_flag = pps->constrained_intra_pred_flag;
  22.258 +  pic->weighted_pred_flag = pps->weighted_pred_flag;
  22.259 +  pic->weighted_bipred_idc = pps->weighted_bipred_idc;
  22.260 +  pic->frame_mbs_only_flag = sps->frame_mbs_only_flag;
  22.261 +  pic->transform_8x8_mode_flag = pps->transform_8x8_mode_flag;
  22.262 +  pic->chroma_qp_index_offset = pps->chroma_qp_index_offset;
  22.263 +  pic->second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset;
  22.264 +  pic->pic_init_qp_minus26 = pps->pic_init_qp_minus26;
  22.265 +  pic->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1;
  22.266 +  pic->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1;
  22.267 +  pic->log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4;
  22.268 +  pic->pic_order_cnt_type = sps->pic_order_cnt_type;
  22.269 +  pic->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4;
  22.270 +  pic->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag;
  22.271 +  pic->direct_8x8_inference_flag = sps->direct_8x8_inference_flag;
  22.272 +  pic->entropy_coding_mode_flag = pps->entropy_coding_mode_flag;
  22.273 +  pic->pic_order_present_flag = pps->pic_order_present_flag;
  22.274 +  pic->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag;
  22.275 +  pic->redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag;
  22.276 +
  22.277 +  memcpy(pic->scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic->scaling_lists_4x4));
  22.278 +  memcpy(pic->scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic->scaling_lists_8x8));
  22.279 +
  22.280 +  /* set num_ref_frames to the number of actually available reference frames,
  22.281 +   * if this is not set generation 3 decoders will fail. */
  22.282 +  /*pic->num_ref_frames =*/
  22.283 +  fill_vdpau_reference_list(&(this->nal_parser->dpb), pic->referenceFrames);
  22.284 +
  22.285 +}
  22.286 +
  22.287 +static int vdpau_decoder_init(video_decoder_t *this_gen)
  22.288 +{
  22.289 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen;
  22.290 +  vo_frame_t *img;
  22.291 +
  22.292 +  this->curr_pts = this->next_pts;
  22.293 +  this->next_pts = 0;
  22.294 +
  22.295 +  if(this->width == 0) {
  22.296 +    this->width = this->nal_parser->current_nal->sps->pic_width;
  22.297 +    this->height = this->nal_parser->current_nal->sps->pic_height;
  22.298 +  }
  22.299 +
  22.300 +  set_ratio(this_gen);
  22.301 +
  22.302 +  _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width );
  22.303 +  _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height );
  22.304 +  _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*this->ratio) );
  22.305 +  _x_stream_info_set( this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step );
  22.306 +  _x_meta_info_set_utf8( this->stream, XINE_META_INFO_VIDEOCODEC, "H264/AVC (vdpau)" );
  22.307 +  xine_event_t event;
  22.308 +  xine_format_change_data_t data;
  22.309 +  event.type = XINE_EVENT_FRAME_FORMAT_CHANGE;
  22.310 +  event.stream = this->stream;
  22.311 +  event.data = &data;
  22.312 +  event.data_length = sizeof(data);
  22.313 +  data.width = this->width;
  22.314 +  data.height = this->height;
  22.315 +  data.aspect = this->ratio;
  22.316 +  xine_event_send( this->stream, &event );
  22.317 +
  22.318 +  switch(this->nal_parser->current_nal->sps->profile_idc) {
  22.319 +    case 100:
  22.320 +      this->profile = VDP_DECODER_PROFILE_H264_HIGH;
  22.321 +      break;
  22.322 +    case 77:
  22.323 +      this->profile = VDP_DECODER_PROFILE_H264_MAIN;
  22.324 +      break;
  22.325 +    case 66:
  22.326 +    default:
  22.327 +      // nvidia's VDPAU doesn't support BASELINE. But most (every?) streams marked BASELINE do not use BASELINE specifics,
  22.328 +      // so, just force MAIN.
  22.329 +      //this->profile = VDP_DECODER_PROFILE_H264_BASELINE;
  22.330 +      this->profile = VDP_DECODER_PROFILE_H264_MAIN;
  22.331 +      break;
  22.332 +  }
  22.333 +
  22.334 +  // Level 4.1 limits:
  22.335 +  int ref_frames = 0;
  22.336 +  if(this->nal_parser->current_nal->sps->num_ref_frames) {
  22.337 +    ref_frames = this->nal_parser->current_nal->sps->num_ref_frames;
  22.338 +  } else {
  22.339 +    uint32_t round_width = (this->width + 15) & ~15;
  22.340 +    uint32_t round_height = (this->height + 15) & ~15;
  22.341 +    uint32_t surf_size = (round_width * round_height * 3) / 2;
  22.342 +    ref_frames = (12 * 1024 * 1024) / surf_size;
  22.343 +  }
  22.344 +
  22.345 +  if (ref_frames > 16) {
  22.346 +      ref_frames = 16;
  22.347 +  }
  22.348 +
  22.349 +  printf("Allocate %d reference frames\n", ref_frames);
  22.350 +  /* get the vdpau context from vo */
  22.351 +  //(this->stream->video_out->open) (this->stream->video_out, this->stream);
  22.352 +  img = this->stream->video_out->get_frame (this->stream->video_out,
  22.353 +                                    this->width, this->height,
  22.354 +                                    this->ratio,
  22.355 +                                    XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS);
  22.356 +
  22.357 +  img->duration = this->video_step;
  22.358 +  img->pts = this->curr_pts;
  22.359 +
  22.360 +  if (this->dangling_img) {
  22.361 +    fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!");
  22.362 +    this->dangling_img->free(this->dangling_img);
  22.363 +  }
  22.364 +  this->dangling_img = img;
  22.365 +  this->last_img = img;
  22.366 +
  22.367 +  this->vdpau_accel = (vdpau_accel_t*)img->accel_data;
  22.368 +
  22.369 +  /*VdpBool is_supported;
  22.370 +  uint32_t max_level, max_references, max_width, max_height;*/
  22.371 +  if(this->vdpau_accel->vdp_runtime_nr > 0) {
  22.372 +   xprintf(this->xine, XINE_VERBOSITY_LOG,
  22.373 +       "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n",
  22.374 +       this->vdpau_accel->vdp_device, this->profile, this->width, this->height);
  22.375 +
  22.376 +   VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device,
  22.377 +       this->profile, this->width, this->height, 16, &this->decoder);
  22.378 +
  22.379 +   if(status != VDP_STATUS_OK) {
  22.380 +     xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status));
  22.381 +     return 0;
  22.382 +   }
  22.383 +  }
  22.384 +  return 1;
  22.385 +}
  22.386 +
  22.387 +static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count)
  22.388 +{
  22.389 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen;
  22.390 +  vo_frame_t *img = this->last_img;
  22.391 +
  22.392 +  if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) {
  22.393 +    dpb_flush(&(this->nal_parser->dpb));
  22.394 +  }
  22.395 +
  22.396 +  VdpPictureInfoH264 pic;
  22.397 +
  22.398 +  fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic);
  22.399 +
  22.400 +  //printf("next decode: %d, %d\n", pic.field_order_cnt[0], pic.field_order_cnt[1]);
  22.401 +
  22.402 +  if(!this->decoder_started && !pic.is_reference)
  22.403 +    return 0;
  22.404 +
  22.405 +  this->decoder_started = 1;
  22.406 +
  22.407 +  struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps;
  22.408 +  struct slice_header *slc = this->nal_parser->current_nal->slc;
  22.409 +
  22.410 +  if(sps->vui_parameters_present_flag &&
  22.411 +      sps->vui_parameters.timing_info_present_flag &&
  22.412 +      this->video_step == 0) {
  22.413 +    this->video_step = 2*90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale));
  22.414 +  }
  22.415 +
  22.416 +  /* flush the DPB if this frame was an IDR */
  22.417 +  //printf("is_idr: %d\n", this->nal_parser->is_idr);
  22.418 +  this->nal_parser->is_idr = 0;
  22.419 +
  22.420 +  /* go and decode a frame */
  22.421 +
  22.422 +  //dump_pictureinfo_h264(&pic);
  22.423 +
  22.424 +  /*int i;
  22.425 +  printf("Decode data: \n");
  22.426 +  for(i = 0; i < ((vdp_buffer->bitstream_bytes < 20) ? vdp_buffer->bitstream_bytes : 20); i++) {
  22.427 +    printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]);
  22.428 +    if((i+1) % 10 == 0)
  22.429 +      printf("\n");
  22.430 +  }
  22.431 +  printf("\n...\n");
  22.432 +  for(i = vdp_buffer->bitstream_bytes - 20; i < vdp_buffer->bitstream_bytes; i++) {
  22.433 +    printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]);
  22.434 +    if((i+1) % 10 == 0)
  22.435 +      printf("\n");
  22.436 +  }*/
  22.437 +
  22.438 +
  22.439 +  if(img == NULL) {
  22.440 +    img = this->stream->video_out->get_frame (this->stream->video_out,
  22.441 +                                              this->width, this->height,
  22.442 +                                              this->ratio,
  22.443 +                                              XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS);
  22.444 +    this->vdpau_accel = (vdpau_accel_t*)img->accel_data;
  22.445 +
  22.446 +    img->duration  = this->video_step;
  22.447 +    img->pts       = this->curr_pts;
  22.448 +
  22.449 +    if (this->dangling_img) {
  22.450 +      fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!");
  22.451 +      this->dangling_img->free(this->dangling_img);
  22.452 +    }
  22.453 +    this->dangling_img = img;
  22.454 +  }
  22.455 +
  22.456 +  if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) {
  22.457 +    printf("VDPAU was preempted. Reinitialise the decoder.\n");
  22.458 +    this->decoder = VDP_INVALID_HANDLE;
  22.459 +    vdpau_h264_reset(this_gen);
  22.460 +    this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr;
  22.461 +    return 0;
  22.462 +  }
  22.463 +
  22.464 +  VdpVideoSurface surface = this->vdpau_accel->surface;
  22.465 +
  22.466 +  //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer->bitstream_bytes, this->curr_pts);
  22.467 +  VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder,
  22.468 +      surface, (VdpPictureInfo*)&pic, 1, vdp_buffer);
  22.469 +
  22.470 +  /* only free the actual data, as the start seq is only
  22.471 +   * locally allocated anyway. */
  22.472 +  if(((uint8_t*)vdp_buffer->bitstream) != NULL) {
  22.473 +    free((uint8_t*)vdp_buffer->bitstream);
  22.474 +  }
  22.475 +
  22.476 +  this->curr_pts = this->next_pts;
  22.477 +  this->next_pts = 0;
  22.478 +
  22.479 +  process_mmc_operations(this->nal_parser);
  22.480 +
  22.481 +  if(status != VDP_STATUS_OK)
  22.482 +  {
  22.483 +    xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n",  this->vdpau_accel->vdp_get_error_string(status));
  22.484 +    if (this->dangling_img)
  22.485 +      this->dangling_img->free(this->dangling_img);
  22.486 +    img = this->last_img = this->dangling_img = NULL;
  22.487 +  }
  22.488 +  else {
  22.489 +    img->bad_frame = 0;
  22.490 +
  22.491 +    if((sps->vui_parameters_present_flag &&
  22.492 +        sps->vui_parameters.pic_struct_present_flag &&
  22.493 +        !this->nal_parser->current_nal->interlaced) ||
  22.494 +        (!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag))
  22.495 +      img->progressive_frame = 1;
  22.496 +    else
  22.497 +      img->progressive_frame = 0;
  22.498 +
  22.499 +    if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic)
  22.500 +      img->repeat_first_field = 1;
  22.501 +    //else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic)
  22.502 +    //  img->duration *= this->nal_parser->current_nal->repeat_pic;
  22.503 +
  22.504 +    /* only bt601 and bt701 handled so far. others seem to be rarely used */
  22.505 +    if(sps->vui_parameters.colour_description_present) {
  22.506 +      switch (sps->vui_parameters.colour_primaries) {
  22.507 +        case 1:
  22.508 +          this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709;
  22.509 +          break;
  22.510 +        case 5:
  22.511 +        case 6:
  22.512 +        default:
  22.513 +          this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601;
  22.514 +          break;
  22.515 +      }
  22.516 +    }
  22.517 +
  22.518 +    this->vdpau_accel->color_standard = this->color_standard;
  22.519 +
  22.520 +    struct decoded_picture *decoded_pic = NULL;
  22.521 +    if(pic.is_reference) {
  22.522 +      if(!slc->field_pic_flag || !this->wait_for_bottom_field) {
  22.523 +        decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img);
  22.524 +        this->last_ref_pic = decoded_pic;
  22.525 +        decoded_pic->used_for_reference = 1;
  22.526 +        dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames);
  22.527 +        this->dangling_img = NULL;
  22.528 +      } else if(slc->field_pic_flag && this->wait_for_bottom_field) {
  22.529 +        if(this->last_ref_pic) {
  22.530 +          decoded_pic = this->last_ref_pic;
  22.531 +          //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal);
  22.532 +          decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt;
  22.533 +          this->last_ref_pic->bottom_is_reference = 1;
  22.534 +        }
  22.535 +      }
  22.536 +    }
  22.537 +
  22.538 +    if(!slc->field_pic_flag ||
  22.539 +        (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) {
  22.540 +
  22.541 +      if(!decoded_pic) {
  22.542 +        decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img);
  22.543 +        //decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt;
  22.544 +        dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames);
  22.545 +        this->dangling_img = NULL;
  22.546 +
  22.547 +        if(decoded_pic->nal->slc->bottom_field_flag)
  22.548 +          decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt;
  22.549 +      }
  22.550 +
  22.551 +      decoded_pic->delayed_output = 1;
  22.552 +
  22.553 +      if(this->wait_for_bottom_field && slc->bottom_field_flag)
  22.554 +        decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt;
  22.555 +
  22.556 +      this->last_img = img = NULL;
  22.557 +
  22.558 +      /* now retrieve the next output frame */
  22.559 +      if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 0)) != NULL) {
  22.560 +        decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt);
  22.561 +        //printf("draw pts: %lld\n", decoded_pic->img->pts);
  22.562 +        decoded_pic->img->draw(decoded_pic->img, this->stream);
  22.563 +        dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic);
  22.564 +      }
  22.565 +
  22.566 +      this->wait_for_bottom_field = 0;
  22.567 +
  22.568 +    } else if(slc->field_pic_flag && !slc->bottom_field_flag) {
  22.569 +      // don't draw yet, second field is missing.
  22.570 +      this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt;
  22.571 +      this->wait_for_bottom_field = 1;
  22.572 +      this->last_img = img;
  22.573 +    }
  22.574 +  }
  22.575 +
  22.576 +  return 1;
  22.577 +}
  22.578 +
  22.579 +/*
  22.580 + * This function receives a buffer of data from the demuxer layer and
  22.581 + * figures out how to handle it based on its header flags.
  22.582 + */
  22.583 +static void vdpau_h264_decode_data (video_decoder_t *this_gen,
  22.584 +  buf_element_t *buf) {
  22.585 +
  22.586 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen;
  22.587 +
  22.588 +  VdpBitstreamBuffer vdp_buffer;
  22.589 +  vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION;
  22.590 +
  22.591 +  /* a video decoder does not care about this flag (?) */
  22.592 +  if (buf->decoder_flags & BUF_FLAG_PREVIEW)
  22.593 +    return;
  22.594 +
  22.595 +  if(buf->decoder_flags & BUF_FLAG_FRAME_START || buf->decoder_flags & BUF_FLAG_FRAME_END)
  22.596 +    this->have_frame_boundary_marks = 1;
  22.597 +
  22.598 +  if (buf->decoder_flags & BUF_FLAG_FRAMERATE) {
  22.599 +    this->video_step = buf->decoder_info[0];
  22.600 +    _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step);
  22.601 +  }
  22.602 +
  22.603 +  if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */
  22.604 +    this->have_frame_boundary_marks = 0;
  22.605 +
  22.606 +    xine_bmiheader *bih = (xine_bmiheader*)buf->content;
  22.607 +    this->width                         = bih->biWidth;
  22.608 +    this->height                        = bih->biHeight;
  22.609 +
  22.610 +    uint8_t *codec_private = buf->content + sizeof(xine_bmiheader);
  22.611 +    uint32_t codec_private_len = bih->biSize - sizeof(xine_bmiheader);
  22.612 +    this->codec_private_len = codec_private_len;
  22.613 +    this->codec_private = malloc(codec_private_len);
  22.614 +    memcpy(this->codec_private, codec_private, codec_private_len);
  22.615 +
  22.616 +    if(codec_private_len > 0) {
  22.617 +      parse_codec_private(this->nal_parser, codec_private, codec_private_len);
  22.618 +    }
  22.619 +  } else if (buf->decoder_flags & BUF_FLAG_SPECIAL) {
  22.620 +    this->have_frame_boundary_marks = 0;
  22.621 +
  22.622 +    if(buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG) {
  22.623 +      uint8_t *codec_private = buf->decoder_info_ptr[2];
  22.624 +      uint32_t codec_private_len = buf->decoder_info[2];
  22.625 +      this->codec_private_len = codec_private_len;
  22.626 +      this->codec_private = malloc(codec_private_len);
  22.627 +      memcpy(this->codec_private, codec_private, codec_private_len);
  22.628 +
  22.629 +      if(codec_private_len > 0) {
  22.630 +        parse_codec_private(this->nal_parser, codec_private, codec_private_len);
  22.631 +      }
  22.632 +    } else if (buf->decoder_info[1] == BUF_SPECIAL_PALETTE) {
  22.633 +      printf("SPECIAL PALETTE is not yet handled\n");
  22.634 +    } else
  22.635 +      printf("UNKNOWN SPECIAL HEADER\n");
  22.636 +
  22.637 +  } else {
  22.638 +    /* parse the first nal packages to retrieve profile type */
  22.639 +    int len = 0;
  22.640 +    uint32_t slice_count;
  22.641 +
  22.642 +    while(len < buf->size && !(this->wait_for_frame_start && !(buf->decoder_flags & BUF_FLAG_FRAME_START))) {
  22.643 +      this->wait_for_frame_start = 0;
  22.644 +      len += parse_frame(this->nal_parser, buf->content + len, buf->size - len,
  22.645 +          (uint8_t*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count);
  22.646 +
  22.647 +      if(this->decoder == VDP_INVALID_HANDLE &&
  22.648 +          this->nal_parser->current_nal->sps != NULL &&
  22.649 +          this->nal_parser->current_nal->sps->pic_width > 0 &&
  22.650 +          this->nal_parser->current_nal->sps->pic_height > 0) {
  22.651 +
  22.652 +        vdpau_decoder_init(this_gen);
  22.653 +      }
  22.654 +
  22.655 +      if(this->decoder != VDP_INVALID_HANDLE &&
  22.656 +          vdp_buffer.bitstream_bytes > 0 &&
  22.657 +          this->nal_parser->current_nal->slc != NULL &&
  22.658 +          this->nal_parser->current_nal->pps != NULL) {
  22.659 +        vdpau_decoder_render(this_gen, &vdp_buffer, slice_count);
  22.660 +      }
  22.661 +
  22.662 +      /* in case the last nal was detected as END_OF_SEQUENCE
  22.663 +       * we will flush the dpb, so that all pictures get drawn
  22.664 +       */
  22.665 +      if(this->nal_parser->last_nal_res == 3)
  22.666 +        vdpau_h264_flush(this_gen);
  22.667 +    }
  22.668 +
  22.669 +    if(buf->pts != 0 && buf->pts != this->next_pts) {
  22.670 +      //printf("next pts: %lld\n", buf->pts);
  22.671 +      this->next_pts = buf->pts;
  22.672 +    }
  22.673 +  }
  22.674 +
  22.675 +  if(buf->decoder_flags & BUF_FLAG_FRAME_END)
  22.676 +    this->wait_for_frame_start = 0;
  22.677 +}
  22.678 +
  22.679 +/*
  22.680 + * This function is called when xine needs to flush the system.
  22.681 + */
  22.682 +static void vdpau_h264_flush (video_decoder_t *this_gen) {
  22.683 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t*) this_gen;
  22.684 +  struct decoded_picture *decoded_pic = NULL;
  22.685 +
  22.686 +  while ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 1)) != NULL) {
  22.687 +    decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt);
  22.688 +    printf("FLUSH draw pts: %lld\n", decoded_pic->img->pts);
  22.689 +    decoded_pic->img->draw(decoded_pic->img, this->stream);
  22.690 +    dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic);
  22.691 +  }
  22.692 +}
  22.693 +
  22.694 +/*
  22.695 + * This function resets the video decoder.
  22.696 + */
  22.697 +static void vdpau_h264_reset (video_decoder_t *this_gen) {
  22.698 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen;
  22.699 +
  22.700 +  printf("vdpau_h264_reset\n");
  22.701 +
  22.702 +  dpb_free_all( &(this->nal_parser->dpb) );
  22.703 +
  22.704 +  if (this->decoder != VDP_INVALID_HANDLE) {
  22.705 +    this->vdpau_accel->vdp_decoder_destroy( this->decoder );
  22.706 +    this->decoder = VDP_INVALID_HANDLE;
  22.707 +  }
  22.708 +
  22.709 +  free_parser(this->nal_parser);
  22.710 +
  22.711 +  this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601;
  22.712 +  this->wait_for_bottom_field = 0;
  22.713 +  this->video_step = 0;
  22.714 +  this->curr_pts = 0;
  22.715 +  this->next_pts = 0;
  22.716 +
  22.717 +  this->nal_parser = init_parser();
  22.718 +  if(this->codec_private_len > 0) {
  22.719 +    parse_codec_private(this->nal_parser, this->codec_private, this->codec_private_len);
  22.720 +
  22.721 +    /* if the stream does not contain frame boundary marks we
  22.722 +     * have to hope that the next nal will start with the next
  22.723 +     * incoming buf... seems to work, though...
  22.724 +     */
  22.725 +    this->wait_for_frame_start = this->have_frame_boundary_marks;
  22.726 +  }
  22.727 +
  22.728 +  if (this->dangling_img) {
  22.729 +    this->dangling_img->free(this->dangling_img);
  22.730 +    this->dangling_img = NULL;
  22.731 +  }
  22.732 +
  22.733 +  this->last_img = NULL;
  22.734 +}
  22.735 +
  22.736 +/*
  22.737 + * The decoder should forget any stored pts values here.
  22.738 + */
  22.739 +static void vdpau_h264_discontinuity (video_decoder_t *this_gen) {
  22.740 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen;
  22.741 +
  22.742 +  this->curr_pts = 0;
  22.743 +  this->next_pts = 0;
  22.744 +  dpb_clear_all_pts(&this->nal_parser->dpb);
  22.745 +}
  22.746 +
  22.747 +/*
  22.748 + * This function frees the video decoder instance allocated to the decoder.
  22.749 + */
  22.750 +static void vdpau_h264_dispose (video_decoder_t *this_gen) {
  22.751 +
  22.752 +  vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen;
  22.753 +
  22.754 +  if (this->dangling_img) {
  22.755 +    this->dangling_img->free(this->dangling_img);
  22.756 +    this->dangling_img = NULL;
  22.757 +  }
  22.758 +
  22.759 +  dpb_free_all( &(this->nal_parser->dpb) );
  22.760 +
  22.761 +  if (this->decoder != VDP_INVALID_HANDLE) {
  22.762 +    this->vdpau_accel->vdp_decoder_destroy( this->decoder );
  22.763 +    this->decoder = VDP_INVALID_HANDLE;
  22.764 +  }
  22.765 +
  22.766 +  this->stream->video_out->close( this->stream->video_out, this->stream );
  22.767 +
  22.768 +  free_parser (this->nal_parser);
  22.769 +  free (this_gen);
  22.770 +}
  22.771 +
  22.772 +/*
  22.773 + * This function allocates, initializes, and returns a private video
  22.774 + * decoder structure.
  22.775 + */
  22.776 +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
  22.777 +
  22.778 +  vdpau_h264_decoder_t  *this ;
  22.779 +
  22.780 +  /* the videoout must be vdpau-capable to support this decoder */
  22.781 +  if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) )
  22.782 +	  return NULL;
  22.783 +
  22.784 +  /* now check if vdpau has free decoder resource */
  22.785 +  vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS );
  22.786 +  vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data;
  22.787 +  int runtime_nr = accel->vdp_runtime_nr;
  22.788 +  img->free(img);
  22.789 +  VdpDecoder decoder;
  22.790 +  VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_H264_MAIN, 1920, 1080, 16, &decoder );
  22.791 +  if ( st!=VDP_STATUS_OK ) {
  22.792 +    lprintf( "can't create vdpau decoder.\n" );
  22.793 +    return 1;
  22.794 +  }
  22.795 +
  22.796 +  accel->vdp_decoder_destroy( decoder );
  22.797 +
  22.798 +  this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t));
  22.799 +
  22.800 +  this->video_decoder.decode_data         = vdpau_h264_decode_data;
  22.801 +  this->video_decoder.flush               = vdpau_h264_flush;
  22.802 +  this->video_decoder.reset               = vdpau_h264_reset;
  22.803 +  this->video_decoder.discontinuity       = vdpau_h264_discontinuity;
  22.804 +  this->video_decoder.dispose             = vdpau_h264_dispose;
  22.805 +
  22.806 +  this->stream                            = stream;
  22.807 +  this->xine                              = stream->xine;
  22.808 +  this->class                             = (vdpau_h264_class_t *) class_gen;
  22.809 +
  22.810 +  this->decoder                           = VDP_INVALID_HANDLE;
  22.811 +  this->vdp_runtime_nr                    = runtime_nr;
  22.812 +  this->color_standard                    = VDP_COLOR_STANDARD_ITUR_BT_601;
  22.813 +
  22.814 +  this->nal_parser = init_parser();
  22.815 +
  22.816 +  (this->stream->video_out->open) (this->stream->video_out, this->stream);
  22.817 +
  22.818 +  return &this->video_decoder;
  22.819 +}
  22.820 +
  22.821 +/*
  22.822 + * This function allocates a private video decoder class and initializes
  22.823 + * the class's member functions.
  22.824 + */
  22.825 +static void *init_plugin (xine_t *xine, void *data) {
  22.826 +
  22.827 +  vdpau_h264_class_t *this;
  22.828 +
  22.829 +  this = (vdpau_h264_class_t *) calloc(1, sizeof(vdpau_h264_class_t));
  22.830 +
  22.831 +  this->decoder_class.open_plugin     = open_plugin;
  22.832 +  this->decoder_class.identifier      = "vdpau_h264";
  22.833 +  this->decoder_class.description     =
  22.834 +	N_("vdpau_h264: h264 decoder plugin using VDPAU hardware decoding.\n"
  22.835 +	   "Must be used along with video_out_vdpau.");
  22.836 +  this->decoder_class.dispose         = default_video_decoder_class_dispose;
  22.837 +
  22.838 +  return this;
  22.839 +}
  22.840 +
  22.841 +/*
  22.842 + * This is a list of all of the internal xine video buffer types that
  22.843 + * this decoder is able to handle. Check src/xine-engine/buffer.h for a
  22.844 + * list of valid buffer types (and add a new one if the one you need does
  22.845 + * not exist). Terminate the list with a 0.
  22.846 + */
  22.847 +static const uint32_t video_types[] = {
  22.848 +  /* BUF_VIDEO_FOOVIDEO, */
  22.849 +  BUF_VIDEO_H264,
  22.850 +  0
  22.851 +};
  22.852 +
  22.853 +/*
  22.854 + * This data structure combines the list of supported xine buffer types and
  22.855 + * the priority that the plugin should be given with respect to other
  22.856 + * plugins that handle the same buffer type. A plugin with priority (n+1)
  22.857 + * will be used instead of a plugin with priority (n).
  22.858 + */
  22.859 +static const decoder_info_t dec_info_video = {
  22.860 +  video_types,         /* supported types */
  22.861 +  7                    /* priority        */
  22.862 +};
  22.863 +
  22.864 +/*
  22.865 + * The plugin catalog entry. This is the only information that this plugin
  22.866 + * will export to the public.
  22.867 + */
  22.868 +const plugin_info_t xine_plugin_info[] EXPORTED = {
  22.869 +  /* { type, API, "name", version, special_info, init_function } */
  22.870 +  { PLUGIN_VIDEO_DECODER, 19, "vdpau_h264", XINE_VERSION_CODE, &dec_info_video, init_plugin },
  22.871 +  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
  22.872 +};
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/src/video_dec/libvdpau/vdpau_mpeg12.c	Fri Nov 20 03:46:10 2009 +0000
    23.3 @@ -0,0 +1,1004 @@
    23.4 +/*
    23.5 + * Copyright (C) 2008 the xine project
    23.6 + * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
    23.7 + *
    23.8 + * This file is part of xine, a free video player.
    23.9 + *
   23.10 + * xine is free software; you can redistribute it and/or modify
   23.11 + * it under the terms of the GNU General Public License as published by
   23.12 + * the Free Software Foundation; either version 2 of the License, or
   23.13 + * (at your option) any later version.
   23.14 + *
   23.15 + * xine is distributed in the hope that it will be useful,
   23.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.18 + * GNU General Public License for more details.
   23.19 + *
   23.20 + * You should have received a copy of the GNU General Public License
   23.21 + * along with this program; if not, write to the Free Software
   23.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   23.23 + *
   23.24 + * vdpau_mpeg12.c, a mpeg1/2 video stream parser using VDPAU hardware decoder
   23.25 + *
   23.26 + */
   23.27 +
   23.28 +/*#define LOG*/
   23.29 +#define LOG_MODULE "vdpau_mpeg12"
   23.30 +
   23.31 +
   23.32 +#include <stdio.h>
   23.33 +#include <stdlib.h>
   23.34 +#include <string.h>
   23.35 +#include <sys/types.h>
   23.36 +#include <unistd.h>
   23.37 +
   23.38 +#include <xine/xine_internal.h>
   23.39 +#include <xine/video_out.h>
   23.40 +#include <xine/buffer.h>
   23.41 +#include <xine/xineutils.h>
   23.42 +#include "accel_vdpau.h"
   23.43 +#include "bits_reader.h"
   23.44 +
   23.45 +#include <vdpau/vdpau.h>
   23.46 +
   23.47 +#define sequence_header_code    0xb3
   23.48 +#define sequence_error_code     0xb4
   23.49 +#define sequence_end_code       0xb7
   23.50 +#define group_start_code        0xb8
   23.51 +#define extension_start_code    0xb5
   23.52 +#define user_data_start_code    0xb2
   23.53 +#define picture_start_code      0x00
   23.54 +#define begin_slice_start_code  0x01
   23.55 +#define end_slice_start_code    0xaf
   23.56 +
   23.57 +#define sequence_ext_sc         1
   23.58 +#define quant_matrix_ext_sc     3
   23.59 +#define picture_coding_ext_sc   8
   23.60 +#define sequence_display_ext_sc 2
   23.61 +
   23.62 +#define I_FRAME   1
   23.63 +#define P_FRAME   2
   23.64 +#define B_FRAME   3
   23.65 +
   23.66 +#define PICTURE_TOP     1
   23.67 +#define PICTURE_BOTTOM  2
   23.68 +#define PICTURE_FRAME   3
   23.69 +
   23.70 +#define WANT_HEADER 1
   23.71 +#define WANT_EXT    2
   23.72 +#define WANT_SLICE  3
   23.73 +
   23.74 +/*#define MAKE_DAT*/ /*do NOT define this, unless you know what you do */
   23.75 +#ifdef MAKE_DAT
   23.76 +static int nframes;
   23.77 +static FILE *outfile;
   23.78 +#endif
   23.79 +
   23.80 +
   23.81 +
   23.82 +/* default intra quant matrix, in zig-zag order */
   23.83 +static const uint8_t default_intra_quantizer_matrix[64] = {
   23.84 +    8,
   23.85 +    16, 16,
   23.86 +    19, 16, 19,
   23.87 +    22, 22, 22, 22,
   23.88 +    22, 22, 26, 24, 26,
   23.89 +    27, 27, 27, 26, 26, 26,
   23.90 +    26, 27, 27, 27, 29, 29, 29,
   23.91 +    34, 34, 34, 29, 29, 29, 27, 27,
   23.92 +    29, 29, 32, 32, 34, 34, 37,
   23.93 +    38, 37, 35, 35, 34, 35,
   23.94 +    38, 38, 40, 40, 40,
   23.95 +    48, 48, 46, 46,
   23.96 +    56, 56, 58,
   23.97 +    69, 69,
   23.98 +    83
   23.99 +};
  23.100 +
  23.101 +uint8_t mpeg2_scan_norm[64] = {
  23.102 +    /* Zig-Zag scan pattern */
  23.103 +     0, 1, 8,16, 9, 2, 3,10,
  23.104 +    17,24,32,25,18,11, 4, 5,
  23.105 +    12,19,26,33,40,48,41,34,
  23.106 +    27,20,13, 6, 7,14,21,28,
  23.107 +    35,42,49,56,57,50,43,36,
  23.108 +    29,22,15,23,30,37,44,51,
  23.109 +    58,59,52,45,38,31,39,46,
  23.110 +    53,60,61,54,47,55,62,63
  23.111 +};
  23.112 +
  23.113 +
  23.114 +
  23.115 +typedef struct {
  23.116 +  VdpPictureInfoMPEG1Or2  vdp_infos; /* first field, also used for frame */
  23.117 +  VdpPictureInfoMPEG1Or2  vdp_infos2; /* second field */
  23.118 +  int                     slices_count, slices_count2;
  23.119 +  uint8_t                 *slices;
  23.120 +  int                     slices_size;
  23.121 +  int                     slices_pos, slices_pos_top;
  23.122 +
  23.123 +  int                     progressive_frame;
  23.124 +  int                     state;
  23.125 +} picture_t;
  23.126 +
  23.127 +
  23.128 +
  23.129 +typedef struct {
  23.130 +  uint32_t    coded_width;
  23.131 +  uint32_t    coded_height;
  23.132 +
  23.133 +  uint64_t    video_step; /* frame duration in pts units */
  23.134 +  double      ratio;
  23.135 +  VdpDecoderProfile profile;
  23.136 +  int         chroma;
  23.137 +  int         top_field_first;
  23.138 +
  23.139 +  int         have_header;
  23.140 +
  23.141 +  uint8_t     *buf; /* accumulate data */
  23.142 +  int         bufseek;
  23.143 +  uint32_t    bufsize;
  23.144 +  uint32_t    bufpos;
  23.145 +  int         start;
  23.146 +
  23.147 +  picture_t   picture;
  23.148 +  vo_frame_t  *forward_ref;
  23.149 +  vo_frame_t  *backward_ref;
  23.150 +
  23.151 +  int64_t    cur_pts, seq_pts;
  23.152 +
  23.153 +  vdpau_accel_t *accel_vdpau;
  23.154 +
  23.155 +  bits_reader_t  br;
  23.156 +
  23.157 +  int         vdp_runtime_nr;
  23.158 +
  23.159 +} sequence_t;
  23.160 +
  23.161 +
  23.162 +
  23.163 +typedef struct {
  23.164 +  video_decoder_class_t   decoder_class;
  23.165 +} vdpau_mpeg12_class_t;
  23.166 +
  23.167 +
  23.168 +
  23.169 +typedef struct vdpau_mpeg12_decoder_s {
  23.170 +  video_decoder_t         video_decoder;  /* parent video decoder structure */
  23.171 +
  23.172 +  vdpau_mpeg12_class_t    *class;
  23.173 +  xine_stream_t           *stream;
  23.174 +
  23.175 +  sequence_t              sequence;
  23.176 +
  23.177 +  VdpDecoder              decoder;
  23.178 +  VdpDecoderProfile       decoder_profile;
  23.179 +  uint32_t                decoder_width;
  23.180 +  uint32_t                decoder_height;
  23.181 +
  23.182 +} vdpau_mpeg12_decoder_t;
  23.183 +
  23.184 +
  23.185 +
  23.186 +static void reset_picture( picture_t *pic )
  23.187 +{
  23.188 +  lprintf( "reset_picture\n" );
  23.189 +  pic->vdp_infos.picture_structure = 0;
  23.190 +  pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0;
  23.191 +  pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1;
  23.192 +  pic->vdp_infos2.concealment_motion_vectors = pic->vdp_infos.concealment_motion_vectors = 0;
  23.193 +  pic->vdp_infos2.intra_vlc_format = pic->vdp_infos.intra_vlc_format = 0;
  23.194 +  pic->vdp_infos2.alternate_scan = pic->vdp_infos.alternate_scan = 0;
  23.195 +  pic->vdp_infos2.q_scale_type = pic->vdp_infos.q_scale_type = 0;
  23.196 +  pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 1;
  23.197 +  pic->slices_count = 0;
  23.198 +  pic->slices_count2 = 0;
  23.199 +  pic->slices_pos = 0;
  23.200 +  pic->slices_pos_top = 0;
  23.201 +  pic->progressive_frame = 0;
  23.202 +  pic->state = WANT_HEADER;
  23.203 +}
  23.204 +
  23.205 +
  23.206 +
  23.207 +static void init_picture( picture_t *pic )
  23.208 +{
  23.209 +  pic->slices_size = 2048;
  23.210 +  pic->slices = (uint8_t*)malloc(pic->slices_size);
  23.211 +  reset_picture( pic );
  23.212 +}
  23.213 +
  23.214 +
  23.215 +
  23.216 +static void reset_sequence( sequence_t *sequence, int free_refs )
  23.217 +{
  23.218 +  sequence->cur_pts = sequence->seq_pts = 0;
  23.219 +  if ( sequence->forward_ref )
  23.220 +    sequence->forward_ref->pts = 0;
  23.221 +  if ( sequence->backward_ref )
  23.222 +    sequence->backward_ref->pts = 0;
  23.223 +
  23.224 +  if ( !free_refs )
  23.225 +    return;
  23.226 +
  23.227 +  sequence->bufpos = 0;
  23.228 +  sequence->bufseek = 0;
  23.229 +  sequence->start = -1;
  23.230 +  if ( sequence->forward_ref )
  23.231 +    sequence->forward_ref->free( sequence->forward_ref );
  23.232 +  sequence->forward_ref = NULL;
  23.233 +  if ( sequence->backward_ref )
  23.234 +    sequence->backward_ref->free( sequence->backward_ref );
  23.235 +  sequence->backward_ref = NULL;
  23.236 +  sequence->top_field_first = 0;
  23.237 +}
  23.238 +
  23.239 +
  23.240 +
  23.241 +static void free_sequence( sequence_t *sequence )
  23.242 +{
  23.243 +  lprintf( "init_sequence\n" );
  23.244 +  sequence->have_header = 0;
  23.245 +  sequence->profile = VDP_DECODER_PROFILE_MPEG1;
  23.246 +  sequence->chroma = 0;
  23.247 +	sequence->video_step = 3600;
  23.248 +  reset_sequence( sequence, 1 );
  23.249 +}
  23.250 +
  23.251 +
  23.252 +
  23.253 +static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len )
  23.254 +{
  23.255 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  23.256 +
  23.257 +  int i, j;
  23.258 +
  23.259 +  if ( sequence->cur_pts ) {
  23.260 +    sequence->seq_pts = sequence->cur_pts;
  23.261 +  }
  23.262 +
  23.263 +  bits_reader_set( &sequence->br, buf );
  23.264 +  sequence->coded_width = read_bits( &sequence->br, 12 );
  23.265 +  lprintf( "coded_width: %d\n", sequence->coded_width );
  23.266 +  sequence->coded_height = read_bits( &sequence->br, 12 );
  23.267 +  lprintf( "coded_height: %d\n", sequence->coded_height );
  23.268 +  int rt = read_bits( &sequence->br, 4 );
  23.269 +  switch ( rt ) {
  23.270 +    case 1: sequence->ratio = 1.0; break;
  23.271 +    case 2: sequence->ratio = 4.0/3.0; break;
  23.272 +    case 3: sequence->ratio = 16.0/9.0; break;
  23.273 +    case 4: sequence->ratio = 2.21; break;
  23.274 +    default: sequence->ratio = (double)sequence->coded_width/(double)sequence->coded_height;
  23.275 +  }
  23.276 +  lprintf( "ratio: %d\n", rt );
  23.277 +  int fr = read_bits( &sequence->br, 4 );
  23.278 +  switch ( fr ) {
  23.279 +    case 1: sequence->video_step = 3913; break; /* 23.976.. */
  23.280 +    case 2: sequence->video_step = 3750; break; /* 24 */
  23.281 +    case 3: sequence->video_step = 3600; break; /* 25 */
  23.282 +    case 4: sequence->video_step = 3003; break; /* 29.97.. */
  23.283 +    case 5: sequence->video_step = 3000; break; /* 30 */
  23.284 +    case 6: sequence->video_step = 1800; break; /* 50 */
  23.285 +    case 7: sequence->video_step = 1525; break; /* 59.94.. */
  23.286 +    case 8: sequence->video_step = 1509; break; /* 60 */
  23.287 +  }
  23.288 +  lprintf( "frame_rate: %d\n", fr );
  23.289 +  int tmp;
  23.290 +  tmp = read_bits( &sequence->br, 18 );
  23.291 +  lprintf( "bit_rate_value: %d\n", tmp );
  23.292 +  tmp = read_bits( &sequence->br, 1 );
  23.293 +  lprintf( "marker_bit: %d\n", tmp );
  23.294 +  tmp = read_bits( &sequence->br, 10 );
  23.295 +  lprintf( "vbv_buffer_size_value: %d\n", tmp );
  23.296 +  tmp = read_bits( &sequence->br, 1 );
  23.297 +  lprintf( "constrained_parameters_flag: %d\n", tmp );
  23.298 +  i = read_bits( &sequence->br, 1 );
  23.299 +  lprintf( "load_intra_quantizer_matrix: %d\n", i );
  23.300 +  if ( i ) {
  23.301 +    for ( j=0; j<64; ++j ) {
  23.302 +      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 );
  23.303 +    }
  23.304 +  }
  23.305 +  else {
  23.306 +    for ( j=0; j<64; ++j ) {
  23.307 +      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];
  23.308 +    }
  23.309 +  }
  23.310 +
  23.311 +  i = read_bits( &sequence->br, 1 );
  23.312 +  lprintf( "load_non_intra_quantizer_matrix: %d\n", i );
  23.313 +  if ( i ) {
  23.314 +    for ( j=0; j<64; ++j ) {
  23.315 +      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 );
  23.316 +    }
  23.317 +  }
  23.318 +  else {
  23.319 +    memset( sequence->picture.vdp_infos.non_intra_quantizer_matrix, 16, 64 );
  23.320 +    memset( sequence->picture.vdp_infos2.non_intra_quantizer_matrix, 16, 64 );
  23.321 +  }
  23.322 +
  23.323 +  if ( !sequence->have_header ) {
  23.324 +    sequence->have_header = 1;
  23.325 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width );
  23.326 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height );
  23.327 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) );
  23.328 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step );
  23.329 +    _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "MPEG1/2 (vdpau)" );
  23.330 +    xine_event_t event;
  23.331 +    xine_format_change_data_t data;
  23.332 +    event.type = XINE_EVENT_FRAME_FORMAT_CHANGE;
  23.333 +    event.stream = this_gen->stream;
  23.334 +    event.data = &data;
  23.335 +    event.data_length = sizeof(data);
  23.336 +    data.width = sequence->coded_width;
  23.337 +    data.height = sequence->coded_height;
  23.338 +    data.aspect = sequence->ratio;
  23.339 +    xine_event_send( this_gen->stream, &event );
  23.340 +  }
  23.341 +}
  23.342 +
  23.343 +
  23.344 +
  23.345 +static void picture_header( sequence_t *sequence, uint8_t *buf, int len )
  23.346 +{
  23.347 +  if ( sequence->picture.state!=WANT_HEADER )
  23.348 +    return;
  23.349 +
  23.350 +  if ( sequence->cur_pts ) {
  23.351 +    sequence->seq_pts = sequence->cur_pts;
  23.352 +  }
  23.353 +
  23.354 +  if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 )
  23.355 +    sequence->picture.vdp_infos.picture_structure = PICTURE_FRAME;
  23.356 +
  23.357 +  VdpPictureInfoMPEG1Or2 *infos = &sequence->picture.vdp_infos;
  23.358 +
  23.359 +  if ( sequence->picture.vdp_infos.picture_structure && sequence->picture.slices_count2 )
  23.360 +      reset_picture( &sequence->picture );
  23.361 +
  23.362 +  if ( sequence->picture.vdp_infos.picture_structure==PICTURE_FRAME ) {
  23.363 +    reset_picture( &sequence->picture );
  23.364 +  }
  23.365 +  else if ( sequence->picture.vdp_infos.picture_structure ) {
  23.366 +    infos = &sequence->picture.vdp_infos2;
  23.367 +  }
  23.368 +
  23.369 +  bits_reader_set( &sequence->br, buf );
  23.370 +  int tmp = read_bits( &sequence->br, 10 );
  23.371 +  lprintf( "temporal_reference: %d\n", tmp );
  23.372 +  infos->picture_coding_type = read_bits( &sequence->br, 3 );
  23.373 +  lprintf( "picture_coding_type: %d\n", infos->picture_coding_type );
  23.374 +  infos->forward_reference = VDP_INVALID_HANDLE;
  23.375 +  infos->backward_reference = VDP_INVALID_HANDLE;
  23.376 +  read_bits( &sequence->br, 16 );
  23.377 +  if ( infos->picture_coding_type > I_FRAME ) {
  23.378 +    infos->full_pel_forward_vector = read_bits( &sequence->br, 1 );
  23.379 +    infos->f_code[0][0] = infos->f_code[0][1] = read_bits( &sequence->br, 3 );
  23.380 +    if ( infos->picture_coding_type==B_FRAME ) {
  23.381 +      infos->full_pel_backward_vector = read_bits( &sequence->br, 1 );
  23.382 +      infos->f_code[1][0] = infos->f_code[1][1] = read_bits( &sequence->br, 3 );
  23.383 +    }
  23.384 +  }
  23.385 +  else {
  23.386 +    infos->full_pel_forward_vector = 0;
  23.387 +    infos->full_pel_backward_vector = 0;
  23.388 +  }
  23.389 +  if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 )
  23.390 +    sequence->picture.state = WANT_SLICE;
  23.391 +  else
  23.392 +    sequence->picture.state = WANT_EXT;
  23.393 +}
  23.394 +
  23.395 +
  23.396 +
  23.397 +static void sequence_extension( sequence_t *sequence, uint8_t *buf, int len )
  23.398 +{
  23.399 +  bits_reader_set( &sequence->br, buf );
  23.400 +  int tmp = read_bits( &sequence->br, 4 );
  23.401 +  lprintf( "extension_start_code_identifier: %d\n", tmp );
  23.402 +  read_bits( &sequence->br, 1 );
  23.403 +  switch ( read_bits( &sequence->br, 3 ) ) {
  23.404 +    case 5: sequence->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; break;
  23.405 +    default: sequence->profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
  23.406 +  }
  23.407 +  read_bits( &sequence->br, 4 );
  23.408 +  tmp = read_bits( &sequence->br, 1 );
  23.409 +  lprintf( "progressive_sequence: %d\n", tmp );
  23.410 +  if ( read_bits( &sequence->br, 2 ) == 2 )
  23.411 +    sequence->chroma = VO_CHROMA_422;
  23.412 +  tmp = read_bits( &sequence->br, 2 );
  23.413 +  lprintf( "horizontal_size_extension: %d\n", tmp );
  23.414 +  tmp = read_bits( &sequence->br, 2 );
  23.415 +  lprintf( "vertical_size_extension: %d\n", tmp );
  23.416 +  tmp = read_bits( &sequence->br, 12 );
  23.417 +  lprintf( "bit_rate_extension: %d\n", tmp );
  23.418 +  tmp = read_bits( &sequence->br, 1 );
  23.419 +  lprintf( "marker_bit: %d\n", tmp );
  23.420 +  tmp = read_bits( &sequence->br, 8 );
  23.421 +  lprintf( "vbv_buffer_size_extension: %d\n", tmp );
  23.422 +  tmp = read_bits( &sequence->br, 1 );
  23.423 +  lprintf( "low_delay: %d\n", tmp );
  23.424 +  tmp = read_bits( &sequence->br, 2 );
  23.425 +  lprintf( "frame_rate_extension_n: %d\n", tmp );
  23.426 +  tmp = read_bits( &sequence->br, 5 );
  23.427 +  lprintf( "frame_rate_extension_d: %d\n", tmp );
  23.428 +}
  23.429 +
  23.430 +
  23.431 +
  23.432 +static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int len )
  23.433 +{
  23.434 +  if ( sequence->picture.state!=WANT_EXT )
  23.435 +    return;
  23.436 +
  23.437 +  VdpPictureInfoMPEG1Or2 *infos = &sequence->picture.vdp_infos;
  23.438 +  if ( infos->picture_structure && infos->picture_structure!=PICTURE_FRAME )
  23.439 +    infos = &sequence->picture.vdp_infos2;
  23.440 +
  23.441 +  bits_reader_set( &sequence->br, buf );
  23.442 +  int tmp = read_bits( &sequence->br, 4 );
  23.443 +  lprintf( "extension_start_code_identifier: %d\n", tmp );
  23.444 +  infos->f_code[0][0] = read_bits( &sequence->br, 4 );
  23.445 +  infos->f_code[0][1] = read_bits( &sequence->br, 4 );
  23.446 +  infos->f_code[1][0] = read_bits( &sequence->br, 4 );
  23.447 +  infos->f_code[1][1] = read_bits( &sequence->br, 4 );
  23.448 +  lprintf( "f_code_0_0: %d\n", infos->f_code[0][0] );
  23.449 +  lprintf( "f_code_0_1: %d\n", infos->f_code[0][1] );
  23.450 +  lprintf( "f_code_1_0: %d\n", infos->f_code[1][0] );
  23.451 +  lprintf( "f_code_1_1: %d\n", infos->f_code[1][1] );
  23.452 +  infos->intra_dc_precision = read_bits( &sequence->br, 2 );
  23.453 +  lprintf( "intra_dc_precision: %d\n", infos->intra_dc_precision );
  23.454 +  infos->picture_structure = read_bits( &sequence->br, 2 );
  23.455 +  lprintf( "picture_structure: %d\n", infos->picture_structure );
  23.456 +  infos->top_field_first = read_bits( &sequence->br, 1 );
  23.457 +  lprintf( "top_field_first: %d\n", infos->top_field_first );
  23.458 +  infos->frame_pred_frame_dct = read_bits( &sequence->br, 1 );
  23.459 +  lprintf( "frame_pred_frame_dct: %d\n", infos->frame_pred_frame_dct );
  23.460 +  infos->concealment_motion_vectors = read_bits( &sequence->br, 1 );
  23.461 +  lprintf( "concealment_motion_vectors: %d\n", infos->concealment_motion_vectors );
  23.462 +  infos->q_scale_type = read_bits( &sequence->br, 1 );
  23.463 +  lprintf( "q_scale_type: %d\n", infos->q_scale_type );
  23.464 +  infos->intra_vlc_format = read_bits( &sequence->br, 1 );
  23.465 +  lprintf( "intra_vlc_format: %d\n", infos->intra_vlc_format );
  23.466 +  infos->alternate_scan = read_bits( &sequence->br, 1 );
  23.467 +  lprintf( "alternate_scan: %d\n", infos->alternate_scan );
  23.468 +  tmp = read_bits( &sequence->br, 1 );
  23.469 +  lprintf( "repeat_first_field: %d\n", tmp );
  23.470 +  tmp = read_bits( &sequence->br, 1 );
  23.471 +  lprintf( "chroma_420_type: %d\n", tmp );
  23.472 +  sequence->picture.progressive_frame = read_bits( &sequence->br, 1 );
  23.473 +  lprintf( "progressive_frame: %d\n", sequence->picture.progressive_frame );
  23.474 +  sequence->picture.state = WANT_SLICE;
  23.475 +}
  23.476 +
  23.477 +
  23.478 +
  23.479 +static void quant_matrix_extension( sequence_t *sequence, uint8_t *buf, int len )
  23.480 +{
  23.481 +  int i, j;
  23.482 +
  23.483 +  bits_reader_set( &sequence->br, buf );
  23.484 +  read_bits( &sequence->br, 4 );
  23.485 +  i = read_bits( &sequence->br, 1 );
  23.486 +  lprintf( "load_intra_quantizer_matrix: %d\n", i );
  23.487 +  if ( i ) {
  23.488 +    for ( j=0; j<64; ++j ) {
  23.489 +      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 );
  23.490 +    }
  23.491 +  }
  23.492 +  else {
  23.493 +    for ( j=0; j<64; ++j ) {
  23.494 +      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];
  23.495 +    }
  23.496 +  }
  23.497 +
  23.498 +  i = read_bits( &sequence->br, 1 );
  23.499 +  lprintf( "load_non_intra_quantizer_matrix: %d\n", i );
  23.500 +  if ( i ) {
  23.501 +    for ( j=0; j<64; ++j ) {
  23.502 +      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 );
  23.503 +    }
  23.504 +  }
  23.505 +  else {
  23.506 +    memset( sequence->picture.vdp_infos.non_intra_quantizer_matrix, 16, 64 );
  23.507 +    memset( sequence->picture.vdp_infos2.non_intra_quantizer_matrix, 16, 64 );
  23.508 +  }
  23.509 +}
  23.510 +
  23.511 +
  23.512 +
  23.513 +static void copy_slice( sequence_t *sequence, uint8_t *buf, int len )
  23.514 +{
  23.515 +  int size = sequence->picture.slices_pos+len;
  23.516 +  if ( sequence->picture.slices_size < size ) {
  23.517 +    sequence->picture.slices_size = size+1024;
  23.518 +    sequence->picture.slices = realloc( sequence->picture.slices, sequence->picture.slices_size );
  23.519 +  }
  23.520 +  xine_fast_memcpy( sequence->picture.slices+sequence->picture.slices_pos, buf, len );
  23.521 +  sequence->picture.slices_pos += len;
  23.522 +  if ( sequence->picture.slices_pos_top )
  23.523 +    sequence->picture.slices_count2++;
  23.524 +  else
  23.525 +    sequence->picture.slices_count++;
  23.526 +}
  23.527 +
  23.528 +
  23.529 +
  23.530 +static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len )
  23.531 +{
  23.532 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  23.533 +
  23.534 +  if ( !sequence->have_header && buf[3]!=sequence_header_code ) {
  23.535 +    lprintf( " ----------- no sequence header yet.\n" );
  23.536 +    return 0;
  23.537 +  }
  23.538 +
  23.539 +  if ( (buf[3] >= begin_slice_start_code) && (buf[3] <= end_slice_start_code) ) {
  23.540 +    lprintf( " ----------- slice_start_code\n" );
  23.541 +    if ( sequence->picture.state==WANT_SLICE )
  23.542 +      copy_slice( sequence, buf, len );
  23.543 +    return 0;
  23.544 +  }
  23.545 +  else if ( sequence->picture.state==WANT_SLICE && sequence->picture.slices_count ) {
  23.546 +    if ( !sequence->picture.slices_count2 ) {
  23.547 +      sequence->picture.slices_pos_top = sequence->picture.slices_pos;
  23.548 +    }
  23.549 +    /* no more slices, decode */
  23.550 +    return 1;
  23.551 +  }
  23.552 +
  23.553 +  switch ( buf[3] ) {
  23.554 +    case sequence_header_code:
  23.555 +      lprintf( " ----------- sequence_header_code\n" );
  23.556 +      sequence_header( this_gen, buf+4, len-4 );
  23.557 +      break;
  23.558 +    case extension_start_code: {
  23.559 +      switch ( buf[4]>>4 ) {
  23.560 +        case sequence_ext_sc:
  23.561 +          lprintf( " ----------- sequence_extension_start_code\n" );
  23.562 +          sequence_extension( sequence, buf+4, len-4 );
  23.563 +          break;
  23.564 +        case quant_matrix_ext_sc:
  23.565 +          lprintf( " ----------- quant_matrix_extension_start_code\n" );
  23.566 +          quant_matrix_extension( sequence, buf+4, len-4 );
  23.567 +          break;
  23.568 +        case picture_coding_ext_sc:
  23.569 +          lprintf( " ----------- picture_coding_extension_start_code\n" );
  23.570 +          picture_coding_extension( sequence, buf+4, len-4 );
  23.571 +          break;
  23.572 +        case sequence_display_ext_sc:
  23.573 +          lprintf( " ----------- sequence_display_extension_start_code\n" );
  23.574 +          break;
  23.575 +      }
  23.576 +      break;
  23.577 +      }
  23.578 +    case user_data_start_code:
  23.579 +      lprintf( " ----------- user_data_start_code\n" );
  23.580 +      break;
  23.581 +    case group_start_code:
  23.582 +      lprintf( " ----------- group_start_code\n" );
  23.583 +      break;
  23.584 +    case picture_start_code:
  23.585 +      lprintf( " ----------- picture_start_code\n" );
  23.586 +      picture_header( sequence, buf+4, len-4 );
  23.587 +      break;
  23.588 +    case sequence_error_code:
  23.589 +      lprintf( " ----------- sequence_error_code\n" );
  23.590 +      break;
  23.591 +    case sequence_end_code:
  23.592 +      lprintf( " ----------- sequence_end_code\n" );
  23.593 +      break;
  23.594 +  }
  23.595 +  return 0;
  23.596 +}
  23.597 +
  23.598 +
  23.599 +
  23.600 +static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel )
  23.601 +{
  23.602 +  sequence_t *seq = (sequence_t*)&vd->sequence;
  23.603 +  picture_t *pic = (picture_t*)&seq->picture;
  23.604 +
  23.605 +  pic->vdp_infos.slice_count = pic->slices_count;
  23.606 +  pic->vdp_infos2.slice_count = pic->slices_count2;
  23.607 +
  23.608 +  VdpStatus st;
  23.609 +  if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) {
  23.610 +    if ( vd->decoder!=VDP_INVALID_HANDLE ) {
  23.611 +      accel->vdp_decoder_destroy( vd->decoder );
  23.612 +      vd->decoder = VDP_INVALID_HANDLE;
  23.613 +    }
  23.614 +    st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder);
  23.615 +    if ( st!=VDP_STATUS_OK )
  23.616 +      lprintf( "failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) );
  23.617 +    else {
  23.618 +      vd->decoder_profile = seq->profile;
  23.619 +      vd->decoder_width = seq->coded_width;
  23.620 +      vd->decoder_height = seq->coded_height;
  23.621 +      seq->vdp_runtime_nr = accel->vdp_runtime_nr;
  23.622 +    }
  23.623 +  }
  23.624 +
  23.625 +  VdpBitstreamBuffer vbit;
  23.626 +  vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION;
  23.627 +  vbit.bitstream = pic->slices;
  23.628 +  vbit.bitstream_bytes = (pic->vdp_infos.picture_structure==PICTURE_FRAME)? pic->slices_pos : pic->slices_pos_top;
  23.629 +  st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit );
  23.630 +  if ( st!=VDP_STATUS_OK )
  23.631 +    lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) );
  23.632 +  else {
  23.633 +    lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n",
  23.634 +              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 );
  23.635 +    VdpPictureInfoMPEG1Or2 *info = &pic->vdp_infos;
  23.636 +    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] );
  23.637 +  }
  23.638 +
  23.639 +  if ( pic->vdp_infos.picture_structure != PICTURE_FRAME ) {
  23.640 +    pic->vdp_infos2.backward_reference = VDP_INVALID_HANDLE;
  23.641 +    pic->vdp_infos2.forward_reference = VDP_INVALID_HANDLE;
  23.642 +    if ( pic->vdp_infos2.picture_coding_type==P_FRAME ) {
  23.643 +      if ( pic->vdp_infos.picture_coding_type==I_FRAME )
  23.644 +        pic->vdp_infos2.forward_reference = accel->surface;
  23.645 +      else
  23.646 +        pic->vdp_infos2.forward_reference = pic->vdp_infos.forward_reference;
  23.647 +    }
  23.648 +    else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) {
  23.649 +      pic->vdp_infos2.forward_reference = pic->vdp_infos.forward_reference;
  23.650 +      pic->vdp_infos2.backward_reference = pic->vdp_infos.backward_reference;
  23.651 +    }
  23.652 +    vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION;
  23.653 +    vbit.bitstream = pic->slices+pic->slices_pos_top;
  23.654 +    vbit.bitstream_bytes = pic->slices_pos-pic->slices_pos_top;
  23.655 +    st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos2, 1, &vbit );
  23.656 +    if ( st!=VDP_STATUS_OK )
  23.657 +      lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) );
  23.658 +    else
  23.659 +      lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n",
  23.660 +                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 );
  23.661 +  }
  23.662 +}
  23.663 +
  23.664 +
  23.665 +
  23.666 +static void decode_picture( vdpau_mpeg12_decoder_t *vd )
  23.667 +{
  23.668 +  sequence_t *seq = (sequence_t*)&vd->sequence;
  23.669 +  picture_t *pic = (picture_t*)&seq->picture;
  23.670 +  vdpau_accel_t *ref_accel;
  23.671 +
  23.672 +  pic->state = WANT_HEADER;
  23.673 +
  23.674 +  if ( seq->profile == VDP_DECODER_PROFILE_MPEG1 )
  23.675 +    pic->vdp_infos.picture_structure=PICTURE_FRAME;
  23.676 +
  23.677 +  if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && !pic->slices_count2 ) {
  23.678 +    /* waiting second field */
  23.679 +    lprintf("********************* no slices_count2 **********************\n");
  23.680 +    return;
  23.681 +  }
  23.682 +
  23.683 +  if ( pic->vdp_infos.picture_coding_type==P_FRAME ) {
  23.684 +    if ( seq->backward_ref ) {
  23.685 +      ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data;
  23.686 +      pic->vdp_infos.forward_reference = ref_accel->surface;
  23.687 +    }
  23.688 +    else
  23.689 +      return;
  23.690 +  }
  23.691 +  else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) {
  23.692 +    if ( seq->forward_ref ) {
  23.693 +      ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data;
  23.694 +      pic->vdp_infos.forward_reference = ref_accel->surface;
  23.695 +    }
  23.696 +    else
  23.697 +      return;
  23.698 +    if ( seq->backward_ref ) {
  23.699 +      ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data;
  23.700 +      pic->vdp_infos.backward_reference = ref_accel->surface;
  23.701 +    }
  23.702 +    else
  23.703 +      return;
  23.704 +  }
  23.705 +
  23.706 +  vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height,
  23.707 +                                                      seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS|seq->chroma );
  23.708 +  vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data;
  23.709 +  if ( !seq->accel_vdpau )
  23.710 +    seq->accel_vdpau = accel;
  23.711 +
  23.712 +  if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) {
  23.713 +    seq->accel_vdpau = accel;
  23.714 +    if ( seq->forward_ref )
  23.715 +      seq->forward_ref->free( seq->forward_ref );
  23.716 +    seq->forward_ref = NULL;
  23.717 +    if ( seq->backward_ref )
  23.718 +      seq->backward_ref->free( seq->backward_ref );
  23.719 +    seq->backward_ref = NULL;
  23.720 +    vd->decoder = VDP_INVALID_HANDLE;
  23.721 +  }
  23.722 +
  23.723 +  decode_render( vd, accel );
  23.724 +
  23.725 +#ifdef MAKE_DAT
  23.726 +  if ( nframes==0 ) {
  23.727 +	fwrite( &seq->coded_width, 1, sizeof(seq->coded_width), outfile );
  23.728 +	fwrite( &seq->coded_height, 1, sizeof(seq->coded_height), outfile );
  23.729 +	fwrite( &seq->ratio, 1, sizeof(seq->ratio), outfile );
  23.730 +	fwrite( &seq->profile, 1, sizeof(seq->profile), outfile );
  23.731 +  }
  23.732 +
  23.733 +  if ( nframes++ < 25 ) {
  23.734 +	fwrite( &pic->vdp_infos, 1, sizeof(pic->vdp_infos), outfile );
  23.735 +	fwrite( &pic->slices_pos, 1, sizeof(pic->slices_pos), outfile );
  23.736 +	fwrite( pic->slices, 1, pic->slices_pos, outfile );
  23.737 +  }
  23.738 +#endif
  23.739 +
  23.740 +  img->drawn = 0;
  23.741 +  img->pts = seq->seq_pts;
  23.742 +  seq->seq_pts = 0; /* reset */
  23.743 +  img->bad_frame = 0;
  23.744 +  img->duration = seq->video_step;
  23.745 +
  23.746 +  /* trying to deal with (french) buggy streams that randomly set bottom_field_first
  23.747 +     while stream is top_field_first. So we assume that when top_field_first
  23.748 +     is set one time, the stream _is_ top_field_first. */
  23.749 +  //printf("pic->vdp_infos.top_field_first = %d\n", pic->vdp_infos.top_field_first);
  23.750 +  if ( pic->vdp_infos.top_field_first )
  23.751 +    seq->top_field_first = 1;
  23.752 +  img->top_field_first = seq->top_field_first;
  23.753 +
  23.754 +  /* progressive_frame is unreliable with most mpeg2 streams */
  23.755 +  if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME )
  23.756 +    img->progressive_frame = 0;
  23.757 +  else
  23.758 +    img->progressive_frame = pic->progressive_frame;
  23.759 +
  23.760 +  if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) {
  23.761 +    if ( pic->vdp_infos.picture_coding_type==I_FRAME && !seq->backward_ref ) {
  23.762 +      img->pts = 0;
  23.763 +      img->draw( img, vd->stream );
  23.764 +      ++img->drawn;
  23.765 +    }
  23.766 +    if ( seq->forward_ref ) {
  23.767 +      seq->forward_ref->drawn = 0;
  23.768 +      seq->forward_ref->free( seq->forward_ref );
  23.769 +    }
  23.770 +    seq->forward_ref = seq->backward_ref;
  23.771 +    if ( seq->forward_ref && !seq->forward_ref->drawn ) {
  23.772 +      seq->forward_ref->draw( seq->forward_ref, vd->stream );
  23.773 +    }
  23.774 +    seq->backward_ref = img;
  23.775 +  }
  23.776 +  else {
  23.777 +    img->draw( img, vd->stream );
  23.778 +    img->free( img );
  23.779 +  }
  23.780 +}
  23.781 +
  23.782 +
  23.783 +
  23.784 +/*
  23.785 + * This function receives a buffer of data from the demuxer layer and
  23.786 + * figures out how to handle it based on its header flags.
  23.787 + */
  23.788 +static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
  23.789 +{
  23.790 +  vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
  23.791 +  sequence_t *seq = (sequence_t*)&this->sequence;
  23.792 +
  23.793 +  /* preview buffers shall not be decoded and drawn -- use them only to supply stream information */
  23.794 +  if (buf->decoder_flags & BUF_FLAG_PREVIEW)
  23.795 +    return;
  23.796 +
  23.797 +  if ( !buf->size )
  23.798 +    return;
  23.799 +
  23.800 +  seq->cur_pts = buf->pts;
  23.801 +
  23.802 +  int size = seq->bufpos+buf->size;
  23.803 +  if ( seq->bufsize < size ) {
  23.804 +    seq->bufsize = size+1024;
  23.805 +    seq->buf = realloc( seq->buf, seq->bufsize );
  23.806 +  }
  23.807 +  xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size );
  23.808 +  seq->bufpos += buf->size;
  23.809 +
  23.810 +  while ( seq->bufseek <= seq->bufpos-4 ) {
  23.811 +    uint8_t *buffer = seq->buf+seq->bufseek;
  23.812 +    if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) {
  23.813 +      if ( seq->start<0 ) {
  23.814 +        seq->start = seq->bufseek;
  23.815 +      }
  23.816 +      else {
  23.817 +        if ( parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ) ) {
  23.818 +          decode_picture( this );
  23.819 +          parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start );
  23.820 +        }
  23.821 +        uint8_t *tmp = (uint8_t*)malloc(seq->bufsize);
  23.822 +        xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek );
  23.823 +        seq->bufpos -= seq->bufseek;
  23.824 +        seq->start = -1;
  23.825 +        seq->bufseek = -1;
  23.826 +        free( seq->buf );
  23.827 +        seq->buf = tmp;
  23.828 +      }
  23.829 +    }
  23.830 +    ++seq->bufseek;
  23.831 +  }
  23.832 +
  23.833 +  /* still image detection -- don't wait for further data if buffer ends in sequence end code */
  23.834 +  if (seq->start >= 0 && seq->buf[seq->start + 3] == sequence_end_code) {
  23.835 +    if (parse_code(this, seq->buf+seq->start, 4)) {
  23.836 +      decode_picture(this);
  23.837 +      parse_code(this, seq->buf+seq->start, 4);
  23.838 +    }
  23.839 +    seq->start = -1;
  23.840 +  }
  23.841 +}
  23.842 +
  23.843 +/*
  23.844 + * This function is called when xine needs to flush the system.
  23.845 + */
  23.846 +static void vdpau_mpeg12_flush (video_decoder_t *this_gen) {
  23.847 +  vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
  23.848 +
  23.849 +  lprintf( "vdpau_mpeg12_flush\n" );
  23.850 +}
  23.851 +
  23.852 +/*
  23.853 + * This function resets the video decoder.
  23.854 + */
  23.855 +static void vdpau_mpeg12_reset (video_decoder_t *this_gen) {
  23.856 +  vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
  23.857 +
  23.858 +  lprintf( "vdpau_mpeg12_reset\n" );
  23.859 +  reset_sequence( &this->sequence, 1 );
  23.860 +}
  23.861 +
  23.862 +/*
  23.863 + * The decoder should forget any stored pts values here.
  23.864 + */
  23.865 +static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) {
  23.866 +  vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
  23.867 +
  23.868 +  lprintf( "vdpau_mpeg12_discontinuity\n" );
  23.869 +  reset_sequence( &this->sequence, 0 );
  23.870 +}
  23.871 +
  23.872 +/*
  23.873 + * This function frees the video decoder instance allocated to the decoder.
  23.874 + */
  23.875 +static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) {
  23.876 +
  23.877 +  vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
  23.878 +
  23.879 +  lprintf( "vdpau_mpeg12_dispose\n" );
  23.880 +
  23.881 +  if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) {
  23.882 +      this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder );
  23.883 +      this->decoder = VDP_INVALID_HANDLE;
  23.884 +    }
  23.885 +
  23.886 +  free_sequence( &this->sequence );
  23.887 +
  23.888 +  this->stream->video_out->close( this->stream->video_out, this->stream );
  23.889 +
  23.890 +  free( this->sequence.picture.slices );
  23.891 +  free( this->sequence.buf );
  23.892 +  free( this_gen );
  23.893 +}
  23.894 +
  23.895 +/*
  23.896 + * This function allocates, initializes, and returns a private video
  23.897 + * decoder structure.
  23.898 + */
  23.899 +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
  23.900 +
  23.901 +  vdpau_mpeg12_decoder_t  *this ;
  23.902 +
  23.903 +  lprintf( "open_plugin\n" );
  23.904 +
  23.905 +  /* the videoout must be vdpau-capable to support this decoder */
  23.906 +  if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_MPEG12) )
  23.907 +    return NULL;
  23.908 +
  23.909 +  /* now check if vdpau has free decoder resource */
  23.910 +  vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS );
  23.911 +  vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data;
  23.912 +  int runtime_nr = accel->vdp_runtime_nr;
  23.913 +  img->free(img);
  23.914 +  VdpDecoder decoder;
  23.915 +  VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, 1920, 1080, 2, &decoder );
  23.916 +  if ( st!=VDP_STATUS_OK ) {
  23.917 +    lprintf( "can't create vdpau decoder.\n" );
  23.918 +    return 1;
  23.919 +  }
  23.920 +
  23.921 +  accel->vdp_decoder_destroy( decoder );
  23.922 +
  23.923 +  this = (vdpau_mpeg12_decoder_t *) calloc(1, sizeof(vdpau_mpeg12_decoder_t));
  23.924 +
  23.925 +  this->video_decoder.decode_data         = vdpau_mpeg12_decode_data;
  23.926 +  this->video_decoder.flush               = vdpau_mpeg12_flush;
  23.927 +  this->video_decoder.reset               = vdpau_mpeg12_reset;
  23.928 +  this->video_decoder.discontinuity       = vdpau_mpeg12_discontinuity;
  23.929 +  this->video_decoder.dispose             = vdpau_mpeg12_dispose;
  23.930 +
  23.931 +  this->stream                            = stream;
  23.932 +  this->class                             = (vdpau_mpeg12_class_t *) class_gen;
  23.933 +
  23.934 +  this->sequence.bufsize = 1024;
  23.935 +  this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize);
  23.936 +  this->sequence.forward_ref = 0;
  23.937 +  this->sequence.backward_ref = 0;
  23.938 +  this->sequence.vdp_runtime_nr = runtime_nr;
  23.939 +  free_sequence( &this->sequence );
  23.940 +  this->sequence.ratio = 1;
  23.941 +
  23.942 +  init_picture( &this->sequence.picture );
  23.943 +
  23.944 +  this->decoder = VDP_INVALID_HANDLE;
  23.945 +  this->sequence.accel_vdpau = NULL;
  23.946 +
  23.947 +  (stream->video_out->open)(stream->video_out, stream);
  23.948 +
  23.949 +#ifdef MAKE_DAT
  23.950 +  outfile = fopen( "/tmp/mpg.dat","w");
  23.951 +  nframes = 0;
  23.952 +#endif
  23.953 +
  23.954 +  return &this->video_decoder;
  23.955 +}
  23.956 +
  23.957 +/*
  23.958 + * This function allocates a private video decoder class and initializes
  23.959 + * the class's member functions.
  23.960 + */
  23.961 +static void *init_plugin (xine_t *xine, void *data) {
  23.962 +
  23.963 +  vdpau_mpeg12_class_t *this;
  23.964 +
  23.965 +  this = (vdpau_mpeg12_class_t *) calloc(1, sizeof(vdpau_mpeg12_class_t));
  23.966 +
  23.967 +  this->decoder_class.open_plugin     = open_plugin;
  23.968 +  this->decoder_class.identifier      = "vdpau_mpeg12";
  23.969 +  this->decoder_class.description     =
  23.970 +	N_("vdpau_mpeg12: mpeg1/2 decoder plugin using VDPAU hardware decoding.\n"
  23.971 +	   "Must be used along with video_out_vdpau.");
  23.972 +  this->decoder_class.dispose         = default_video_decoder_class_dispose;
  23.973 +
  23.974 +  return this;
  23.975 +}
  23.976 +
  23.977 +/*
  23.978 + * This is a list of all of the internal xine video buffer types that
  23.979 + * this decoder is able to handle. Check src/xine-engine/buffer.h for a
  23.980 + * list of valid buffer types (and add a new one if the one you need does
  23.981 + * not exist). Terminate the list with a 0.
  23.982 + */
  23.983 +static const uint32_t video_types[] = {
  23.984 +  BUF_VIDEO_MPEG,
  23.985 +  0
  23.986 +};
  23.987 +
  23.988 +/*
  23.989 + * This data structure combines the list of supported xine buffer types and
  23.990 + * the priority that the plugin should be given with respect to other
  23.991 + * plugins that handle the same buffer type. A plugin with priority (n+1)
  23.992 + * will be used instead of a plugin with priority (n).
  23.993 + */
  23.994 +static const decoder_info_t dec_info_video = {
  23.995 +  video_types,         /* supported types */
  23.996 +  8                    /* priority        */
  23.997 +};
  23.998 +
  23.999 +/*
 23.1000 + * The plugin catalog entry. This is the only information that this plugin
 23.1001 + * will export to the public.
 23.1002 + */
 23.1003 +const plugin_info_t xine_plugin_info[] EXPORTED = {
 23.1004 +  /* { type, API, "name", version, special_info, init_function } */
 23.1005 +  { PLUGIN_VIDEO_DECODER, 19, "vdpau_mpeg12", XINE_VERSION_CODE, &dec_info_video, init_plugin },
 23.1006 +  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
 23.1007 +};
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/src/video_dec/libvdpau/vdpau_vc1.c	Fri Nov 20 03:46:10 2009 +0000
    24.3 @@ -0,0 +1,1170 @@
    24.4 +/*
    24.5 + * Copyright (C) 2008 the xine project
    24.6 + * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
    24.7 + *
    24.8 + * This file is part of xine, a free video player.
    24.9 + *
   24.10 + * xine is free software; you can redistribute it and/or modify
   24.11 + * it under the terms of the GNU General Public License as published by
   24.12 + * the Free Software Foundation; either version 2 of the License, or
   24.13 + * (at your option) any later version.
   24.14 + *
   24.15 + * xine is distributed in the hope that it will be useful,
   24.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.18 + * GNU General Public License for more details.
   24.19 + *
   24.20 + * You should have received a copy of the GNU General Public License
   24.21 + * along with this program; if not, write to the Free Software
   24.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
   24.23 + *
   24.24 + * vdpau_vc1.c, a vc1 video stream parser using VDPAU hardware decoder
   24.25 + *
   24.26 + */
   24.27 +
   24.28 +/*#define LOG*/
   24.29 +#define LOG_MODULE "vdpau_vc1"
   24.30 +
   24.31 +
   24.32 +#include <stdio.h>
   24.33 +#include <stdlib.h>
   24.34 +#include <string.h>
   24.35 +#include <sys/types.h>
   24.36 +#include <unistd.h>
   24.37 +
   24.38 +#include <xine/xine_internal.h>
   24.39 +#include <xine/video_out.h>
   24.40 +#include <xine/buffer.h>
   24.41 +#include <xine/xineutils.h>
   24.42 +#include "accel_vdpau.h"
   24.43 +#include "bits_reader.h"
   24.44 +
   24.45 +#include <vdpau/vdpau.h>
   24.46 +
   24.47 +#define sequence_header_code    0x0f
   24.48 +#define sequence_end_code       0x0a
   24.49 +#define entry_point_code        0x0e
   24.50 +#define frame_start_code        0x0d
   24.51 +#define field_start_code        0x0c
   24.52 +#define slice_start_code        0x0b
   24.53 +
   24.54 +#define PICTURE_FRAME            0
   24.55 +#define PICTURE_FRAME_INTERLACE  2
   24.56 +#define PICTURE_FIELD_INTERLACE  3
   24.57 +
   24.58 +#define I_FRAME   0
   24.59 +#define P_FRAME   1
   24.60 +#define B_FRAME   3
   24.61 +#define BI_FRAME  4
   24.62 +
   24.63 +#define FIELDS_I_I    0
   24.64 +#define FIELDS_I_P    1
   24.65 +#define FIELDS_P_I    2
   24.66 +#define FIELDS_P_P    3
   24.67 +#define FIELDS_B_B    4
   24.68 +#define FIELDS_B_BI   5
   24.69 +#define FIELDS_BI_B   6
   24.70 +#define FIELDS_BI_BI  7
   24.71 +
   24.72 +#define MODE_STARTCODE  0
   24.73 +#define MODE_FRAME      1
   24.74 +
   24.75 +/*#define MAKE_DAT*/ /*do NOT define this, unless you know what you do */
   24.76 +#ifdef MAKE_DAT
   24.77 +static int nframes;
   24.78 +static FILE *outfile;
   24.79 +#endif
   24.80 +
   24.81 +
   24.82 +
   24.83 +const double aspect_ratio[] = {
   24.84 +  0.0,
   24.85 +  1.0,
   24.86 +  12./11.,
   24.87 +  10./11.,
   24.88 +  16./11.,
   24.89 +  40./33.,
   24.90 +  24./11.,
   24.91 +  20./11.,
   24.92 +  32./11.,
   24.93 +  80./33.,
   24.94 +  18./11.,
   24.95 +  15./11.,
   24.96 +  64./33.,
   24.97 +  160./99.
   24.98 +};
   24.99 +
  24.100 +
  24.101 +
  24.102 +typedef struct {
  24.103 +  VdpPictureInfoVC1       vdp_infos;
  24.104 +  int                     slices;
  24.105 +  int                     fptype;
  24.106 +  int                     field;
  24.107 +  int                     header_size;
  24.108 +  int                     hrd_param_flag;
  24.109 +  int                     hrd_num_leaky_buckets;
  24.110 +  int                     repeat_first_field;
  24.111 +  int                     top_field_first;
  24.112 +  int                     skipped;
  24.113 +} picture_t;
  24.114 +
  24.115 +
  24.116 +
  24.117 +typedef struct {
  24.118 +  uint32_t    coded_width;
  24.119 +  uint32_t    coded_height;
  24.120 +
  24.121 +  uint64_t    video_step; /* frame duration in pts units */
  24.122 +  double      ratio;
  24.123 +  VdpDecoderProfile profile;
  24.124 +
  24.125 +  int         mode;
  24.126 +  int         have_header;
  24.127 +
  24.128 +  uint8_t     *buf; /* accumulate data */
  24.129 +  int         bufseek;
  24.130 +  int         start;
  24.131 +  int         code_start, current_code;
  24.132 +  uint32_t    bufsize;
  24.133 +  uint32_t    bufpos;
  24.134 +
  24.135 +  picture_t   picture;
  24.136 +  vo_frame_t  *forward_ref;
  24.137 +  vo_frame_t  *backward_ref;
  24.138 +
  24.139 +  int64_t    seq_pts;
  24.140 +  int64_t    cur_pts;
  24.141 +
  24.142 +  vdpau_accel_t *accel_vdpau;
  24.143 +
  24.144 +  bits_reader_t br;
  24.145 +
  24.146 +  int         vdp_runtime_nr;
  24.147 +
  24.148 +} sequence_t;
  24.149 +
  24.150 +
  24.151 +
  24.152 +typedef struct {
  24.153 +  video_decoder_class_t   decoder_class;
  24.154 +} vdpau_vc1_class_t;
  24.155 +
  24.156 +
  24.157 +
  24.158 +typedef struct vdpau_vc1_decoder_s {
  24.159 +  video_decoder_t         video_decoder;  /* parent video decoder structure */
  24.160 +
  24.161 +  vdpau_vc1_class_t    *class;
  24.162 +  xine_stream_t           *stream;
  24.163 +
  24.164 +  sequence_t              sequence;
  24.165 +
  24.166 +  VdpDecoder              decoder;
  24.167 +  VdpDecoderProfile       decoder_profile;
  24.168 +  uint32_t                decoder_width;
  24.169 +  uint32_t                decoder_height;
  24.170 +
  24.171 +} vdpau_vc1_decoder_t;
  24.172 +
  24.173 +
  24.174 +
  24.175 +static void init_picture( picture_t *pic )
  24.176 +{
  24.177 +  memset( pic, 0, sizeof( picture_t ) );
  24.178 +}
  24.179 +
  24.180 +
  24.181 +
  24.182 +static void reset_picture( picture_t *pic )
  24.183 +{
  24.184 +  pic->slices = 1;
  24.185 +}
  24.186 +
  24.187 +
  24.188 +
  24.189 +static void reset_sequence( sequence_t *sequence )
  24.190 +{
  24.191 +  lprintf( "reset_sequence\n" );
  24.192 +  sequence->bufpos = 0;
  24.193 +  sequence->bufseek = 0;
  24.194 +  sequence->start = -1;
  24.195 +  sequence->code_start = sequence->current_code = 0;
  24.196 +  sequence->seq_pts = sequence->cur_pts = 0;
  24.197 +  if ( sequence->forward_ref )
  24.198 +    sequence->forward_ref->free( sequence->forward_ref );
  24.199 +  sequence->forward_ref = NULL;
  24.200 +  if ( sequence->backward_ref )
  24.201 +    sequence->backward_ref->free( sequence->backward_ref );
  24.202 +  sequence->backward_ref = NULL;
  24.203 +  reset_picture( &sequence->picture );
  24.204 +}
  24.205 +
  24.206 +
  24.207 +
  24.208 +static void init_sequence( sequence_t *sequence )
  24.209 +{
  24.210 +  lprintf( "init_sequence\n" );
  24.211 +  sequence->have_header = 0;
  24.212 +  sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE;
  24.213 +  sequence->ratio = 0;
  24.214 +  sequence->video_step = 0;
  24.215 +  sequence->picture.hrd_param_flag = 0;
  24.216 +  reset_sequence( sequence );
  24.217 +}
  24.218 +
  24.219 +
  24.220 +
  24.221 +static void update_metadata( vdpau_vc1_decoder_t *this_gen )
  24.222 +{
  24.223 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.224 +
  24.225 +  if ( !sequence->have_header ) {
  24.226 +    sequence->have_header = 1;
  24.227 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width );
  24.228 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height );
  24.229 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) );
  24.230 +    _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step );
  24.231 +    _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" );
  24.232 +    xine_event_t event;
  24.233 +    xine_format_change_data_t data;
  24.234 +    event.type = XINE_EVENT_FRAME_FORMAT_CHANGE;
  24.235 +    event.stream = this_gen->stream;
  24.236 +    event.data = &data;
  24.237 +    event.data_length = sizeof(data);
  24.238 +    data.width = sequence->coded_width;
  24.239 +    data.height = sequence->coded_height;
  24.240 +    data.aspect = sequence->ratio;
  24.241 +    xine_event_send( this_gen->stream, &event );
  24.242 +  }
  24.243 +}
  24.244 +
  24.245 +
  24.246 +
  24.247 +static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len )
  24.248 +{
  24.249 +  lprintf( "sequence_header_advanced\n" );
  24.250 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.251 +
  24.252 +  if ( len < 5 )
  24.253 +    return;
  24.254 +
  24.255 +  sequence->profile = VDP_DECODER_PROFILE_VC1_ADVANCED;
  24.256 +  lprintf("VDP_DECODER_PROFILE_VC1_ADVANCED\n");
  24.257 +  bits_reader_set( &sequence->br, buf );
  24.258 +  read_bits( &sequence->br, 15 );
  24.259 +  sequence->picture.vdp_infos.postprocflag = read_bits( &sequence->br, 1 );
  24.260 +  sequence->coded_width = read_bits( &sequence->br, 12 )<<1;
  24.261 +  sequence->coded_height = (read_bits( &sequence->br, 12 )+1)<<1;
  24.262 +  sequence->picture.vdp_infos.pulldown = read_bits( &sequence->br, 1 );
  24.263 +  sequence->picture.vdp_infos.interlace = read_bits( &sequence->br, 1 );
  24.264 +  sequence->picture.vdp_infos.tfcntrflag = read_bits( &sequence->br, 1 );
  24.265 +  sequence->picture.vdp_infos.finterpflag = read_bits( &sequence->br, 1 );
  24.266 +  read_bits( &sequence->br, 1 );
  24.267 +  sequence->picture.vdp_infos.psf = read_bits( &sequence->br, 1 );
  24.268 +  sequence->picture.vdp_infos.maxbframes = 7;
  24.269 +  if ( read_bits( &sequence->br, 1 ) ) {
  24.270 +    double w, h;
  24.271 +    int ar=0;
  24.272 +    w = read_bits( &sequence->br, 14 )+1;
  24.273 +    h = read_bits( &sequence->br, 14 )+1;
  24.274 +    if ( read_bits( &sequence->br, 1 ) ) {
  24.275 +      ar = read_bits( &sequence->br, 4 );
  24.276 +    }
  24.277 +    if ( ar==15 ) {
  24.278 +      w = read_bits( &sequence->br, 8 );
  24.279 +      h = read_bits( &sequence->br, 8 );
  24.280 +      sequence->ratio = w/h;
  24.281 +      lprintf("aspect_ratio (w/h) = %f\n", sequence->ratio);
  24.282 +    }
  24.283 +    else if ( ar && ar<14 ) {
  24.284 +      sequence->ratio = sequence->coded_width*aspect_ratio[ar]/sequence->coded_height;
  24.285 +      lprintf("aspect_ratio = %f\n", sequence->ratio);
  24.286 +    }
  24.287 +
  24.288 +    if ( read_bits( &sequence->br, 1 ) ) {
  24.289 +      if ( read_bits( &sequence->br, 1 ) ) {
  24.290 +        int exp = read_bits( &sequence->br, 16 );
  24.291 +        lprintf("framerate exp = %d\n", exp);
  24.292 +      }
  24.293 +      else {
  24.294 +        double nr = read_bits( &sequence->br, 8 );
  24.295 +        switch ((int)nr) {
  24.296 +          case 1: nr = 24000; break;
  24.297 +          case 2: nr = 25000; break;
  24.298 +          case 3: nr = 30000; break;
  24.299 +          case 4: nr = 50000; break;
  24.300 +          case 5: nr = 60000; break;
  24.301 +          default: nr = 0;
  24.302 +        }
  24.303 +        double dr = read_bits( &sequence->br, 4 );
  24.304 +        switch ((int)dr) {
  24.305 +          case 2: dr = 1001; break;
  24.306 +          default: dr = 1000;
  24.307 +        }
  24.308 +        sequence->video_step = 90000/(nr/dr);
  24.309 +        lprintf("framerate = %f video_step = %d\n", nr/dr, sequence->video_step);
  24.310 +      }
  24.311 +    }
  24.312 +    if ( read_bits( &sequence->br, 1 ) ) {
  24.313 +	  int col = read_bits( &sequence->br, 8 );
  24.314 +      lprintf("color_standard = %d\n", col);
  24.315 +      read_bits( &sequence->br, 16 );
  24.316 +    }
  24.317 +  }
  24.318 +  sequence->picture.hrd_param_flag = read_bits( &sequence->br, 1 );
  24.319 +  if ( sequence->picture.hrd_param_flag )
  24.320 +    sequence->picture.hrd_num_leaky_buckets = read_bits( &sequence->br, 5 );
  24.321 +
  24.322 +  update_metadata( this_gen );
  24.323 +}
  24.324 +
  24.325 +
  24.326 +
  24.327 +static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len )
  24.328 +{
  24.329 +  lprintf( "sequence_header\n" );
  24.330 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.331 +
  24.332 +  if ( len < 4 )
  24.333 +    return;
  24.334 +
  24.335 +  bits_reader_set( &sequence->br, buf );
  24.336 +  switch ( read_bits( &sequence->br, 2 ) ) {
  24.337 +    case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; lprintf("VDP_DECODER_PROFILE_VC1_SIMPLE\n"); break;
  24.338 +    case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("VDP_DECODER_PROFILE_VC1_MAIN\n"); break;
  24.339 +    case 2: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("vc1_complex profile not supported by vdpau, trying vc1_main.\n"); break;
  24.340 +    case 3: return sequence_header_advanced( this_gen, buf, len ); break;
  24.341 +    default: return; /* illegal value, broken header? */
  24.342 +  }
  24.343 +  read_bits( &sequence->br, 10 );
  24.344 +  sequence->picture.vdp_infos.loopfilter = read_bits( &sequence->br, 1 );
  24.345 +  read_bits( &sequence->br, 1 );
  24.346 +  sequence->picture.vdp_infos.multires = read_bits( &sequence->br, 1 );
  24.347 +  read_bits( &sequence->br, 1 );
  24.348 +  sequence->picture.vdp_infos.fastuvmc = read_bits( &sequence->br, 1 );
  24.349 +  sequence->picture.vdp_infos.extended_mv = read_bits( &sequence->br, 1 );
  24.350 +  sequence->picture.vdp_infos.dquant = read_bits( &sequence->br, 2 );
  24.351 +  sequence->picture.vdp_infos.vstransform = read_bits( &sequence->br, 1 );
  24.352 +  read_bits( &sequence->br, 1 );
  24.353 +  sequence->picture.vdp_infos.overlap = read_bits( &sequence->br, 1 );
  24.354 +  sequence->picture.vdp_infos.syncmarker = read_bits( &sequence->br, 1 );
  24.355 +  sequence->picture.vdp_infos.rangered = read_bits( &sequence->br, 1 );
  24.356 +  sequence->picture.vdp_infos.maxbframes = read_bits( &sequence->br, 3 );
  24.357 +  sequence->picture.vdp_infos.quantizer = read_bits( &sequence->br, 2 );
  24.358 +  sequence->picture.vdp_infos.finterpflag = read_bits( &sequence->br, 1 );
  24.359 +
  24.360 +  update_metadata( this_gen );
  24.361 +}
  24.362 +
  24.363 +
  24.364 +
  24.365 +static void entry_point( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len )
  24.366 +{
  24.367 +  lprintf( "entry_point\n" );
  24.368 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.369 +
  24.370 +  bits_reader_set( &sequence->br, buf );
  24.371 +  read_bits( &sequence->br, 2 );
  24.372 +  sequence->picture.vdp_infos.panscan_flag = read_bits( &sequence->br, 1 );
  24.373 +  sequence->picture.vdp_infos.refdist_flag = read_bits( &sequence->br, 1 );
  24.374 +  sequence->picture.vdp_infos.loopfilter = read_bits( &sequence->br, 1 );
  24.375 +  sequence->picture.vdp_infos.fastuvmc = read_bits( &sequence->br, 1 );
  24.376 +  sequence->picture.vdp_infos.extended_mv = read_bits( &sequence->br, 1 );
  24.377 +  sequence->picture.vdp_infos.dquant = read_bits( &sequence->br, 2 );
  24.378 +  sequence->picture.vdp_infos.vstransform = read_bits( &sequence->br, 1 );
  24.379 +  sequence->picture.vdp_infos.overlap = read_bits( &sequence->br, 1 );
  24.380 +  sequence->picture.vdp_infos.quantizer = read_bits( &sequence->br, 2 );
  24.381 +
  24.382 +  if ( sequence->picture.hrd_param_flag ) {
  24.383 +    int i;
  24.384 +    for ( i=0; i<sequence->picture.hrd_num_leaky_buckets; ++i )
  24.385 +      read_bits( &sequence->br, 8 );
  24.386 +  }
  24.387 +
  24.388 +  if ( read_bits( &sequence->br, 1 ) ) {
  24.389 +    sequence->coded_width = (read_bits( &sequence->br, 12 )+1)<<1;
  24.390 +    sequence->coded_height = (read_bits( &sequence->br, 12 )+1)<<1;
  24.391 +  }
  24.392 +
  24.393 +  if ( sequence->picture.vdp_infos.extended_mv )
  24.394 +    sequence->picture.vdp_infos.extended_dmv = read_bits( &sequence->br, 1 );
  24.395 +
  24.396 +  sequence->picture.vdp_infos.range_mapy_flag = read_bits( &sequence->br, 1 );
  24.397 +  if ( sequence->picture.vdp_infos.range_mapy_flag ) {
  24.398 +    sequence->picture.vdp_infos.range_mapy = read_bits( &sequence->br, 3 );
  24.399 +  }
  24.400 +  sequence->picture.vdp_infos.range_mapuv_flag = read_bits( &sequence->br, 1 );
  24.401 +  if ( sequence->picture.vdp_infos.range_mapuv_flag ) {
  24.402 +    sequence->picture.vdp_infos.range_mapuv = read_bits( &sequence->br, 3 );
  24.403 +  }
  24.404 +}
  24.405 +
  24.406 +
  24.407 +
  24.408 +static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len )
  24.409 +{
  24.410 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.411 +  picture_t *pic = (picture_t*)&sequence->picture;
  24.412 +  VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos);
  24.413 +  int tmp;
  24.414 +
  24.415 +  lprintf("picture_header\n");
  24.416 +
  24.417 +  bits_reader_set( &sequence->br, buf );
  24.418 +  read_bits( &sequence->br, 2 );
  24.419 +
  24.420 +  if ( info->finterpflag )
  24.421 +    read_bits( &sequence->br, 1 );
  24.422 +  if ( info->rangered ) {
  24.423 +    /*info->rangered &= ~2;
  24.424 +    info->rangered |= get_bits( buf,off++,1 ) << 1;*/
  24.425 +    info->rangered = (read_bits( &sequence->br, 1 ) << 1) +1;
  24.426 +  }
  24.427 +  if ( !info->maxbframes ) {
  24.428 +    if ( read_bits( &sequence->br, 1 ) )
  24.429 +      info->picture_type = P_FRAME;
  24.430 +    else
  24.431 +      info->picture_type = I_FRAME;
  24.432 +  }
  24.433 +  else {
  24.434 +    if ( read_bits( &sequence->br, 1 ) )
  24.435 +      info->picture_type = P_FRAME;
  24.436 +    else {
  24.437 +      if ( read_bits( &sequence->br, 1 ) )
  24.438 +        info->picture_type = I_FRAME;
  24.439 +      else
  24.440 +        info->picture_type = B_FRAME;
  24.441 +    }
  24.442 +  }
  24.443 +  if ( info->picture_type == B_FRAME ) {
  24.444 +    tmp = read_bits( &sequence->br, 3 );
  24.445 +    if ( tmp==7 ) {
  24.446 +      tmp = (tmp<<4) | read_bits( &sequence->br, 4 );
  24.447 +      if ( tmp==127 )
  24.448 +        info->picture_type = BI_FRAME;
  24.449 +    }
  24.450 +  }
  24.451 +}
  24.452 +
  24.453 +
  24.454 +
  24.455 +static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len )
  24.456 +{
  24.457 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.458 +  picture_t *pic = (picture_t*)&sequence->picture;
  24.459 +  VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos);
  24.460 +
  24.461 +  lprintf("picture_header_advanced\n");
  24.462 +
  24.463 +  bits_reader_set( &sequence->br, buf );
  24.464 +
  24.465 +  if ( info->interlace ) {
  24.466 +    lprintf("frame->interlace=1\n");
  24.467 +    if ( !read_bits( &sequence->br, 1 ) ) {
  24.468 +      lprintf("progressive frame\n");
  24.469 +      info->frame_coding_mode = PICTURE_FRAME;
  24.470 +    }
  24.471 +    else {
  24.472 +      if ( !read_bits( &sequence->br, 1 ) ) {
  24.473 +        lprintf("frame interlaced\n");
  24.474 +        info->frame_coding_mode = PICTURE_FRAME_INTERLACE;
  24.475 +      }
  24.476 +      else {
  24.477 +        lprintf("field interlaced\n");
  24.478 +        info->frame_coding_mode = PICTURE_FIELD_INTERLACE;
  24.479 +      }
  24.480 +    }
  24.481 +  }
  24.482 +  if ( info->interlace && info->frame_coding_mode == PICTURE_FIELD_INTERLACE ) {
  24.483 +    pic->fptype = read_bits( &sequence->br, 3 );
  24.484 +    switch ( pic->fptype ) {
  24.485 +      case FIELDS_I_I:
  24.486 +      case FIELDS_I_P:
  24.487 +        info->picture_type = I_FRAME; break;
  24.488 +      case FIELDS_P_I:
  24.489 +      case FIELDS_P_P:
  24.490 +        info->picture_type = P_FRAME; break;
  24.491 +      case FIELDS_B_B:
  24.492 +      case FIELDS_B_BI:
  24.493 +        info->picture_type = B_FRAME; break;
  24.494 +      default:
  24.495 +        info->picture_type = BI_FRAME;
  24.496 +    }
  24.497 +  }
  24.498 +  else {
  24.499 +    if ( !read_bits( &sequence->br, 1 ) )
  24.500 +      info->picture_type = P_FRAME;
  24.501 +    else {
  24.502 +      if ( !read_bits( &sequence->br, 1 ) )
  24.503 +        info->picture_type = B_FRAME;
  24.504 +      else {
  24.505 +        if ( !read_bits( &sequence->br, 1 ) )
  24.506 +          info->picture_type = I_FRAME;
  24.507 +        else {
  24.508 +          if ( !read_bits( &sequence->br, 1 ) )
  24.509 +            info->picture_type = BI_FRAME;
  24.510 +          else {
  24.511 +            info->picture_type = P_FRAME;
  24.512 +            pic->skipped = 1;
  24.513 +          }
  24.514 +        }
  24.515 +      }
  24.516 +    }
  24.517 +  }
  24.518 +  if ( info->tfcntrflag ) {
  24.519 +    lprintf("tfcntrflag=1\n");
  24.520 +    read_bits( &sequence->br, 8 );
  24.521 +  }
  24.522 +  if ( info->pulldown && info->interlace ) {
  24.523 +    pic->top_field_first = read_bits( &sequence->br, 1 );
  24.524 +    pic->repeat_first_field = read_bits( &sequence->br, 1 );
  24.525 +  }
  24.526 +}
  24.527 +
  24.528 +
  24.529 +
  24.530 +static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len )
  24.531 +{
  24.532 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.533 +  int off=0;
  24.534 +
  24.535 +  while ( off < (len-4) ) {
  24.536 +    uint8_t *buffer = buf+off;
  24.537 +    if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) {
  24.538 +      switch ( buffer[3] ) {
  24.539 +        case sequence_header_code: sequence_header( this_gen, buf+off+4, len-off-4 ); break;
  24.540 +        case entry_point_code: entry_point( this_gen, buf+off+4, len-off-4 ); break;
  24.541 +      }
  24.542 +    }
  24.543 +    ++off;
  24.544 +  }
  24.545 +  if ( !sequence->have_header )
  24.546 +    sequence_header( this_gen, buf, len );
  24.547 +}
  24.548 +
  24.549 +
  24.550 +
  24.551 +static void remove_emulation_prevention( uint8_t *src, uint8_t *dst, int src_len, int *dst_len )
  24.552 +{
  24.553 +  int i;
  24.554 +  int len = 0;
  24.555 +  int removed = 0;
  24.556 +
  24.557 +  for ( i=0; i<src_len-3; ++i ) {
  24.558 +    if ( src[i]==0 && src[i+1]==0 && src[i+2]==3 ) {
  24.559 +      lprintf("removed emulation prevention byte\n");
  24.560 +      dst[len++] = src[i];
  24.561 +      dst[len++] = src[i+1];
  24.562 +      i += 2;
  24.563 +      ++removed;
  24.564 +    }
  24.565 +    else {
  24.566 +      memcpy( dst+len, src+i, 4 );
  24.567 +      ++len;
  24.568 +    }
  24.569 +  }
  24.570 +  for ( ; i<src_len; ++i )
  24.571 +    dst[len++] = src[i];
  24.572 +  *dst_len = src_len-removed;
  24.573 +}
  24.574 +
  24.575 +
  24.576 +
  24.577 +static int parse_code( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len )
  24.578 +{
  24.579 +  sequence_t *sequence = (sequence_t*)&this_gen->sequence;
  24.580 +
  24.581 +  if ( !sequence->have_header && buf[3]!=sequence_header_code )
  24.582 +    return 0;
  24.583 +
  24.584 +  if ( sequence->code_start == frame_start_code ) {
  24.585 +    if ( sequence->current_code==field_start_code || sequence->current_code==slice_start_code ) {
  24.586 +	  sequence->picture.slices++;
  24.587 +      return -1;
  24.588 +	}
  24.589 +    return 1; /* frame complete, decode */
  24.590 +  }
  24.591 +
  24.592 +  switch ( buf[3] ) {
  24.593 +    int dst_len;
  24.594 +    uint8_t *tmp;
  24.595 +    case sequence_header_code:
  24.596 +      lprintf("sequence_header_code\n");
  24.597 +      tmp = malloc( len );
  24.598 +      remove_emulation_prevention( buf, tmp, len, &dst_len );
  24.599 +      sequence_header( this_gen, tmp+4, dst_len-4 );
  24.600 +      free( tmp );
  24.601 +      break;
  24.602 +    case entry_point_code:
  24.603 +      lprintf("entry_point_code\n");
  24.604 +      tmp = malloc( len );
  24.605 +      remove_emulation_prevention( buf, tmp, len, &dst_len );
  24.606 +      entry_point( this_gen, tmp+4, dst_len-4 );
  24.607 +      free( tmp );
  24.608 +      break;
  24.609 +    case sequence_end_code:
  24.610 +      lprintf("sequence_end_code\n");
  24.611 +      break;
  24.612 +    case frame_start_code:
  24.613 +      lprintf("frame_start_code, len=%d\n", len);
  24.614 +      break;
  24.615 +    case field_start_code:
  24.616 +      lprintf("field_start_code\n");
  24.617 +      break;
  24.618 +    case slice_start_code:
  24.619 +      lprintf("slice_start_code, len=%d\n", len);
  24.620 +      break;
  24.621 +  }
  24.622 +  return 0;
  24.623 +}
  24.624 +
  24.625 +
  24.626 +
  24.627 +static void duplicate_image( vdpau_vc1_decoder_t *vd, vo_frame_t *dst )
  24.628 +{
  24.629 +  lprintf("duplicate_image\n");
  24.630 +  sequence_t *seq = (sequence_t*)&vd->sequence;
  24.631 +  picture_t *pic = (picture_t*)&seq->picture;
  24.632 +
  24.633 +  if ( !seq->backward_ref ) /* Should not happen! */
  24.634 +    return;
  24.635 +
  24.636 +  dst->proc_duplicate_frame_data( dst, seq->backward_ref );
  24.637 +}
  24.638 +
  24.639 +
  24.640 +
  24.641 +static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_t *buf, int len )
  24.642 +{
  24.643 +  sequence_t *seq = (sequence_t*)&vd->sequence;
  24.644 +  picture_t *pic = (picture_t*)&seq->picture;
  24.645 +
  24.646 +  VdpStatus st;
  24.647 +  if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) {
  24.648 +    if ( vd->decoder!=VDP_INVALID_HANDLE ) {
  24.649 +      accel->vdp_decoder_destroy( vd->decoder );
  24.650 +      vd->decoder = VDP_INVALID_HANDLE;
  24.651 +    }
  24.652 +    st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder);
  24.653 +    if ( st!=VDP_STATUS_OK )
  24.654 +      printf( "vdpau_vc1: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) );
  24.655 +    else {
  24.656 +      lprintf( "decoder created.\n" );
  24.657 +      vd->decoder_profile = seq->profile;
  24.658 +      vd->decoder_width = seq->coded_width;
  24.659 +      vd->decoder_height = seq->coded_height;
  24.660 +      seq->vdp_runtime_nr = accel->vdp_runtime_nr;
  24.661 +    }
  24.662 +  }
  24.663 +
  24.664 +  VdpBitstreamBuffer vbit;
  24.665 +  vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION;
  24.666 +  vbit.bitstream = buf;
  24.667 +  vbit.bitstream_bytes = len;
  24.668 +  if ( pic->field )
  24.669 +    vbit.bitstream_bytes = pic->field;
  24.670 +  st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit );
  24.671 +  if ( st!=VDP_STATUS_OK )
  24.672 +    printf( "vdpau_vc1: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) );
  24.673 +  else {
  24.674 +    lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n",
  24.675 +              pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts );
  24.676 +  }
  24.677 +  VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos);
  24.678 +  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,
  24.679 +           info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag,
  24.680 +           info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy,
  24.681 +           info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant );
  24.682 +
  24.683 +  if ( pic->field ) {
  24.684 +    int old_type = pic->vdp_infos.picture_type;
  24.685 +    switch ( pic->fptype ) {
  24.686 +      case FIELDS_I_I:
  24.687 +      case FIELDS_P_I:
  24.688 +        pic->vdp_infos.picture_type = I_FRAME;
  24.689 +        pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE;
  24.690 +        pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE;
  24.691 +        break;
  24.692 +      case FIELDS_I_P:
  24.693 +      case FIELDS_P_P:
  24.694 +        pic->vdp_infos.forward_reference = accel->surface;
  24.695 +        pic->vdp_infos.picture_type = P_FRAME; break;
  24.696 +      case FIELDS_B_B:
  24.697 +      case FIELDS_BI_B:
  24.698 +        pic->vdp_infos.picture_type = B_FRAME;
  24.699 +        break;
  24.700 +      default:
  24.701 +        pic->vdp_infos.picture_type = BI_FRAME;
  24.702 +    }
  24.703 +    vbit.bitstream = buf+pic->field+4;
  24.704 +    vbit.bitstream_bytes = len-pic->field-4;
  24.705 +    st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit );
  24.706 +    if ( st!=VDP_STATUS_OK )
  24.707 +      printf( "vdpau_vc1: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) );
  24.708 +    else {
  24.709 +      lprintf( "DECODER SUCCESS (second field): slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n",
  24.710 +                pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts );
  24.711 +    }
  24.712 +    VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos);
  24.713 +    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,
  24.714 +             info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag,
  24.715 +             info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy,
  24.716 +             info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant );
  24.717 +
  24.718 +    pic->vdp_infos.picture_type = old_type;
  24.719 +  }
  24.720 +}
  24.721 +
  24.722 +
  24.723 +
  24.724 +static int search_field( vdpau_vc1_decoder_t *vd, uint8_t *buf, int len )
  24.725 +{
  24.726 +  int i;
  24.727 +  lprintf("search_fields, len=%d\n", len);
  24.728 +  for ( i=0; i<len-4; ++i ) {
  24.729 +    if ( buf[i]==0 && buf[i+1]==0 && buf[i+2]==1 && buf[i+3]==field_start_code ) {
  24.730 +      lprintf("found field_start_code at %d\n", i);
  24.731 +      return i;
  24.732 +    }
  24.733 +  }
  24.734 +  return 0;
  24.735 +}
  24.736 +
  24.737 +
  24.738 +
  24.739 +static void decode_picture( vdpau_vc1_decoder_t *vd )
  24.740 +{
  24.741 +  sequence_t *seq = (sequence_t*)&vd->sequence;
  24.742 +  picture_t *pic = (picture_t*)&seq->picture;
  24.743 +  vdpau_accel_t *ref_accel;
  24.744 +  int field;
  24.745 +
  24.746 +  uint8_t *buf;
  24.747 +  int len;
  24.748 +
  24.749 +  pic->skipped = 0;
  24.750 +  pic->field = 0;
  24.751 +
  24.752 +  if ( seq->mode == MODE_FRAME ) {
  24.753 +    buf = seq->buf;
  24.754 +    len = seq->bufpos;
  24.755 +    if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED )
  24.756 +      picture_header_advanced( vd, buf, len );
  24.757 +    else
  24.758 +      picture_header( vd, buf, len );
  24.759 +
  24.760 +    if ( len < 2 )
  24.761 +      pic->skipped = 1;
  24.762 +  }
  24.763 +  else {
  24.764 +    seq->picture.vdp_infos.slice_count = seq->picture.slices;
  24.765 +    buf = seq->buf+seq->start+4;
  24.766 +    len = seq->bufseek-seq->start-4;
  24.767 +    if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) {
  24.768 +      int tmplen = (len>50) ? 50 : len;
  24.769 +      uint8_t *tmp = malloc( tmplen );
  24.770 +      remove_emulation_prevention( buf, tmp, tmplen, &tmplen );
  24.771 +      picture_header_advanced( vd, tmp, tmplen );
  24.772 +      free( tmp );
  24.773 +    }
  24.774 +    else
  24.775 +      picture_header( vd, buf, len );
  24.776 +
  24.777 +    if ( len < 2 )
  24.778 +      pic->skipped = 1;
  24.779 +  }
  24.780 +
  24.781 +  if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode == PICTURE_FIELD_INTERLACE ) {
  24.782 +    if ( !(field = search_field( vd, buf, len )) )
  24.783 +      lprintf("error, no fields found!\n");
  24.784 +    else
  24.785 +      pic->field = field;
  24.786 +  }
  24.787 +
  24.788 +  pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE;
  24.789 +  pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE;
  24.790 +
  24.791 +  if ( pic->vdp_infos.picture_type==P_FRAME ) {
  24.792 +    if ( seq->backward_ref ) {
  24.793 +      ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data;
  24.794 +      pic->vdp_infos.forward_reference = ref_accel->surface;
  24.795 +    }
  24.796 +    else {
  24.797 +	  reset_picture( &seq->picture );
  24.798 +      return;
  24.799 +	}
  24.800 +  }
  24.801 +  else if ( pic->vdp_infos.picture_type>=B_FRAME ) {
  24.802 +    if ( seq->forward_ref ) {
  24.803 +      ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data;
  24.804 +      pic->vdp_infos.forward_reference = ref_accel->surface;
  24.805 +    }
  24.806 +    else {
  24.807 +	  reset_picture( &seq->picture );
  24.808 +      return;
  24.809 +	}
  24.810 +    if ( seq->backward_ref ) {
  24.811 +      ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data;
  24.812 +      pic->vdp_infos.backward_reference = ref_accel->surface;
  24.813 +    }
  24.814 +    else {
  24.815 +	  reset_picture( &seq->picture );
  24.816 +      return;
  24.817 +	}
  24.818 +  }
  24.819 +
  24.820 +  vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height,
  24.821 +                                                      seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS );
  24.822 +  vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data;
  24.823 +  if ( !seq->accel_vdpau )
  24.824 +    seq->accel_vdpau = accel;
  24.825 +
  24.826 +  if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) {
  24.827 +    seq->accel_vdpau = accel;
  24.828 +    if ( seq->forward_ref )
  24.829 +      seq->forward_ref->free( seq->forward_ref );
  24.830 +    seq->forward_ref = NULL;
  24.831 +    if ( seq->backward_ref )
  24.832 +      seq->backward_ref->free( seq->backward_ref );
  24.833 +    seq->backward_ref = NULL;
  24.834 +    vd->decoder = VDP_INVALID_HANDLE;
  24.835 +  }
  24.836 +
  24.837 +  if ( pic->skipped )
  24.838 +    duplicate_image( vd, img );
  24.839 +  else
  24.840 +    decode_render( vd, accel, buf, len );
  24.841 +
  24.842 +
  24.843 +#ifdef MAKE_DAT
  24.844 +  if ( nframes==0 ) {
  24.845 +	fwrite( &seq->coded_width, 1, sizeof(seq->coded_width), outfile );
  24.846 +	fwrite( &seq->coded_height, 1, sizeof(seq->coded_height), outfile );
  24.847 +	fwrite( &seq->ratio, 1, sizeof(seq->ratio), outfile );
  24.848 +	fwrite( &seq->profile, 1, sizeof(seq->profile), outfile );
  24.849 +  }
  24.850 +
  24.851 +  if ( nframes++ < 25 ) {
  24.852 +	fwrite( &pic->vdp_infos, 1, sizeof(pic->vdp_infos), outfile );
  24.853 +	fwrite( &len, 1, sizeof(len), outfile );
  24.854 +	fwrite( buf, 1, len, outfile );
  24.855 +	printf( "picture_type = %d\n", pic->vdp_infos.picture_type);
  24.856 +  }
  24.857 +#endif
  24.858 +
  24.859 +  if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode ) {
  24.860 +    img->progressive_frame = 0;
  24.861 +    img->top_field_first = pic->top_field_first;
  24.862 +  }
  24.863 +  else {
  24.864 +    img->progressive_frame = 1;
  24.865 +    img->top_field_first = 1;
  24.866 +  }
  24.867 +  img->pts = seq->seq_pts;
  24.868 +  img->bad_frame = 0;
  24.869 +  img->duration = seq->video_step;
  24.870 +  accel->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709;
  24.871 +
  24.872 +  if ( pic->vdp_infos.picture_type<B_FRAME ) {
  24.873 +    if ( pic->vdp_infos.picture_type==I_FRAME && !seq->backward_ref ) {
  24.874 +      img->pts = 0;
  24.875 +      img->draw( img, vd->stream );
  24.876 +      ++img->drawn;
  24.877 +    }
  24.878 +    if ( seq->forward_ref ) {
  24.879 +      seq->forward_ref->drawn = 0;
  24.880 +      seq->forward_ref->free( seq->forward_ref );
  24.881 +    }
  24.882 +    seq->forward_ref = seq->backward_ref;
  24.883 +    if ( seq->forward_ref && !seq->forward_ref->drawn ) {
  24.884 +      seq->forward_ref->draw( seq->forward_ref, vd->stream );
  24.885 +    }
  24.886 +    seq->backward_ref = img;
  24.887 +  }
  24.888 +  else {
  24.889 +    img->draw( img, vd->stream );
  24.890 +    img->free( img );
  24.891 +  }
  24.892 +
  24.893 +  seq->seq_pts +=seq->video_step;
  24.894 +
  24.895 +  reset_picture( &seq->picture );
  24.896 +}
  24.897 +
  24.898 +
  24.899 +
  24.900 +/*
  24.901 + * This function receives a buffer of data from the demuxer layer and
  24.902 + * figures out how to handle it based on its header flags.
  24.903 + */
  24.904 +static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf)
  24.905 +{
  24.906 +  vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen;
  24.907 +  sequence_t *seq = (sequence_t*)&this->sequence;
  24.908 +
  24.909 +  /* a video decoder does not care about this flag (?) */
  24.910 +  if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
  24.911 +    lprintf("BUF_FLAG_PREVIEW\n");
  24.912 +  }
  24.913 +
  24.914 +  if (buf->decoder_flags & BUF_FLAG_FRAMERATE) {
  24.915 +    lprintf("BUF_FLAG_FRAMERATE=%d\n", buf->decoder_info[0]);
  24.916 +    if ( buf->decoder_info[0] > 0 ) {
  24.917 +      this->sequence.video_step = buf->decoder_info[0];
  24.918 +      _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->sequence.video_step);
  24.919 +    }
  24.920 +  }
  24.921 +
  24.922 +  if (buf->decoder_flags & BUF_FLAG_HEADER) {
  24.923 +    lprintf("BUF_FLAG_HEADER\n");
  24.924 +  }
  24.925 +
  24.926 +  if (buf->decoder_flags & BUF_FLAG_ASPECT) {
  24.927 +    lprintf("BUF_FLAG_ASPECT\n");
  24.928 +    seq->ratio = (double)buf->decoder_info[1]/(double)buf->decoder_info[2];
  24.929 +    lprintf("arx=%d ary=%d ratio=%f\n", buf->decoder_info[1], buf->decoder_info[2], seq->ratio);
  24.930 +  }
  24.931 +
  24.932 +  if (buf->decoder_flags & BUF_FLAG_FRAME_START) {
  24.933 +    lprintf("BUF_FLAG_FRAME_START\n");
  24.934 +    seq->seq_pts = buf->pts;
  24.935 +  }
  24.936 +
  24.937 +  if ( !buf->size )
  24.938 +    return;
  24.939 +
  24.940 +  seq->cur_pts = buf->pts;
  24.941 +
  24.942 +  if (buf->decoder_flags & BUF_FLAG_STDHEADER) {
  24.943 +    lprintf("BUF_FLAG_STDHEADER\n");
  24.944 +    xine_bmiheader *bih = (xine_bmiheader *) buf->content;
  24.945 +    int bs = sizeof( xine_bmiheader );
  24.946 +    seq->coded_width = bih->biWidth;
  24.947 +    seq->coded_height = bih->biHeight;
  24.948 +    lprintf( "width=%d height=%d\n", bih->biWidth, bih->biHeight );
  24.949 +    if ( buf->size > bs ) {
  24.950 +      seq->mode = MODE_FRAME;
  24.951 +      parse_header( this, buf->content+bs, buf->size-bs );
  24.952 +    }
  24.953 +    return;
  24.954 +  }
  24.955 +
  24.956 +  int size = seq->bufpos+buf->size;
  24.957 +  if ( seq->bufsize < size ) {
  24.958 +    seq->bufsize = size+10000;
  24.959 +    seq->buf = realloc( seq->buf, seq->bufsize );
  24.960 +    lprintf("sequence buffer realloced = %d\n", seq->bufsize );
  24.961 +  }
  24.962 +  xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size );
  24.963 +  seq->bufpos += buf->size;
  24.964 +
  24.965 +  if ( seq->mode == MODE_FRAME ) {
  24.966 +    if (buf->decoder_flags & BUF_FLAG_FRAME_END) {
  24.967 +      lprintf("BUF_FLAG_FRAME_END\n");
  24.968 +      seq->picture.vdp_infos.slice_count = 1;
  24.969 +      decode_picture( this );
  24.970 +      seq->bufpos = 0;
  24.971 +    }
  24.972 +  }
  24.973 +  else {
  24.974 +    int res;
  24.975 +    while ( seq->bufseek <= seq->bufpos-4 ) {
  24.976 +      uint8_t *buffer = seq->buf+seq->bufseek;
  24.977 +      if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) {
  24.978 +		seq->current_code = buffer[3];
  24.979 +		lprintf("current_code = %d\n", seq->current_code);
  24.980 +        if ( seq->start<0 ) {
  24.981 +          seq->start = seq->bufseek;
  24.982 +          seq->code_start = buffer[3];
  24.983 +		  lprintf("code_start = %d\n", seq->code_start);
  24.984 +          if ( seq->cur_pts )
  24.985 +            seq->seq_pts = seq->cur_pts;
  24.986 +        }
  24.987 +        else {
  24.988 +          res = parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start );
  24.989 +          if ( res==1 ) {
  24.990 +            decode_picture( this );
  24.991 +            parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start );
  24.992 +          }
  24.993 +          if ( res!=-1 ) {
  24.994 +            uint8_t *tmp = (uint8_t*)malloc(seq->bufsize);
  24.995 +            xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek );
  24.996 +            seq->bufpos -= seq->bufseek;
  24.997 +            seq->start = -1;
  24.998 +            seq->bufseek = -1;
  24.999 +            free( seq->buf );
 24.1000 +            seq->buf = tmp;
 24.1001 +          }
 24.1002 +        }
 24.1003 +      }
 24.1004 +      ++seq->bufseek;
 24.1005 +    }
 24.1006 +  }
 24.1007 +}
 24.1008 +
 24.1009 +
 24.1010 +
 24.1011 +/*
 24.1012 + * This function is called when xine needs to flush the system.
 24.1013 + */
 24.1014 +static void vdpau_vc1_flush (video_decoder_t *this_gen) {
 24.1015 +  vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen;
 24.1016 +
 24.1017 +  lprintf( "vdpau_vc1_flush\n" );
 24.1018 +}
 24.1019 +
 24.1020 +/*
 24.1021 + * This function resets the video decoder.
 24.1022 + */
 24.1023 +static void vdpau_vc1_reset (video_decoder_t *this_gen) {
 24.1024 +  vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen;
 24.1025 +
 24.1026 +  lprintf( "vdpau_vc1_reset\n" );
 24.1027 +  reset_sequence( &this->sequence );
 24.1028 +}
 24.1029 +
 24.1030 +/*
 24.1031 + * The decoder should forget any stored pts values here.
 24.1032 + */
 24.1033 +static void vdpau_vc1_discontinuity (video_decoder_t *this_gen) {
 24.1034 +  vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen;
 24.1035 +
 24.1036 +  lprintf( "vdpau_vc1_discontinuity\n" );
 24.1037 +}
 24.1038 +
 24.1039 +/*
 24.1040 + * This function frees the video decoder instance allocated to the decoder.
 24.1041 + */
 24.1042 +static void vdpau_vc1_dispose (video_decoder_t *this_gen) {
 24.1043 +
 24.1044 +  vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen;
 24.1045 +
 24.1046 +  lprintf( "vdpau_vc1_dispose\n" );
 24.1047 +
 24.1048 +  if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) {
 24.1049 +      this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder );
 24.1050 +      this->decoder = VDP_INVALID_HANDLE;
 24.1051 +    }
 24.1052 +
 24.1053 +  reset_sequence( &this->sequence );
 24.1054 +
 24.1055 +  this->stream->video_out->close( this->stream->video_out, this->stream );
 24.1056 +
 24.1057 +  free( this->sequence.buf );
 24.1058 +  free( this_gen );
 24.1059 +}
 24.1060 +
 24.1061 +/*
 24.1062 + * This function allocates, initializes, and returns a private video
 24.1063 + * decoder structure.
 24.1064 + */
 24.1065 +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
 24.1066 +
 24.1067 +  vdpau_vc1_decoder_t  *this ;
 24.1068 +
 24.1069 +  lprintf( "open_plugin\n" );
 24.1070 +
 24.1071 +  /* the videoout must be vdpau-capable to support this decoder */
 24.1072 +  if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_VC1) )
 24.1073 +    return NULL;
 24.1074 +
 24.1075 +  /* now check if vdpau has free decoder resource */
 24.1076 +  vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS );
 24.1077 +  vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data;
 24.1078 +  int runtime_nr = accel->vdp_runtime_nr;
 24.1079 +  img->free(img);
 24.1080 +  VdpDecoder decoder;
 24.1081 +  VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, 1920, 1080, 2, &decoder );
 24.1082 +  if ( st!=VDP_STATUS_OK ) {
 24.1083 +    lprintf( "can't create vdpau decoder.\n" );
 24.1084 +    return 1;
 24.1085 +  }
 24.1086 +
 24.1087 +  accel->vdp_decoder_destroy( decoder );
 24.1088 +
 24.1089 +  this = (vdpau_vc1_decoder_t *) calloc(1, sizeof(vdpau_vc1_decoder_t));
 24.1090 +
 24.1091 +  this->video_decoder.decode_data         = vdpau_vc1_decode_data;
 24.1092 +  this->video_decoder.flush               = vdpau_vc1_flush;
 24.1093 +  this->video_decoder.reset               = vdpau_vc1_reset;
 24.1094 +  this->video_decoder.discontinuity       = vdpau_vc1_discontinuity;
 24.1095 +  this->video_decoder.dispose             = vdpau_vc1_dispose;
 24.1096 +
 24.1097 +  this->stream                            = stream;
 24.1098 +  this->class                             = (vdpau_vc1_class_t *) class_gen;
 24.1099 +
 24.1100 +  this->sequence.bufsize = 10000;
 24.1101 +  this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize);
 24.1102 +  this->sequence.forward_ref = 0;
 24.1103 +  this->sequence.backward_ref = 0;
 24.1104 +  this->sequence.vdp_runtime_nr = runtime_nr;
 24.1105 +  init_sequence( &this->sequence );
 24.1106 +
 24.1107 +  init_picture( &this->sequence.picture );
 24.1108 +
 24.1109 +  this->decoder = VDP_INVALID_HANDLE;
 24.1110 +  this->sequence.accel_vdpau = NULL;
 24.1111 +  this->sequence.mode = MODE_STARTCODE;
 24.1112 +
 24.1113 +  (stream->video_out->open)(stream->video_out, stream);
 24.1114 +
 24.1115 +#ifdef MAKE_DAT
 24.1116 +  outfile = fopen( "/tmp/vc1.dat","w");
 24.1117 +  nframes = 0;
 24.1118 +#endif
 24.1119 +
 24.1120 +  return &this->video_decoder;
 24.1121 +}
 24.1122 +
 24.1123 +/*
 24.1124 + * This function allocates a private video decoder class and initializes
 24.1125 + * the class's member functions.
 24.1126 + */
 24.1127 +static void *init_plugin (xine_t *xine, void *data) {
 24.1128 +
 24.1129 +  vdpau_vc1_class_t *this;
 24.1130 +
 24.1131 +  this = (vdpau_vc1_class_t *) calloc(1, sizeof(vdpau_vc1_class_t));
 24.1132 +
 24.1133 +  this->decoder_class.open_plugin     = open_plugin;
 24.1134 +  this->decoder_class.identifier      = "vdpau_vc1";
 24.1135 +  this->decoder_class.description     =
 24.1136 +	N_("vdpau_vc1: vc1 decoder plugin using VDPAU hardware decoding.\n"
 24.1137 +	   "Must be used along with video_out_vdpau.");
 24.1138 +  this->decoder_class.dispose         = default_video_decoder_class_dispose;
 24.1139 +
 24.1140 +  return this;
 24.1141 +}
 24.1142 +
 24.1143 +/*
 24.1144 + * This is a list of all of the internal xine video buffer types that
 24.1145 + * this decoder is able to handle. Check src/xine-engine/buffer.h for a
 24.1146 + * list of valid buffer types (and add a new one if the one you need does
 24.1147 + * not exist). Terminate the list with a 0.
 24.1148 + */
 24.1149 +static const uint32_t video_types[] = {
 24.1150 +  BUF_VIDEO_VC1, BUF_VIDEO_WMV9,
 24.1151 +  0
 24.1152 +};
 24.1153 +
 24.1154 +/*
 24.1155 + * This data structure combines the list of supported xine buffer types and
 24.1156 + * the priority that the plugin should be given with respect to other
 24.1157 + * plugins that handle the same buffer type. A plugin with priority (n+1)
 24.1158 + * will be used instead of a plugin with priority (n).
 24.1159 + */
 24.1160 +static const decoder_info_t dec_info_video = {
 24.1161 +  video_types,         /* supported types */
 24.1162 +  8                    /* priority        */
 24.1163 +};
 24.1164 +
 24.1165 +/*
 24.1166 + * The plugin catalog entry. This is the only information that this plugin
 24.1167 + * will export to the public.
 24.1168 + */
 24.1169 +const plugin_info_t xine_plugin_info[] EXPORTED = {
 24.1170 +  /* { type, API, "name", version, special_info, init_function } */
 24.1171 +  { PLUGIN_VIDEO_DECODER, 19, "vdpau_vc1", XINE_VERSION_CODE, &dec_info_video, init_plugin },
 24.1172 +  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
 24.1173 +};
    25.1 --- a/src/video_out/Makefile.am	Thu Nov 19 15:29:17 2009 +0000
    25.2 +++ b/src/video_out/Makefile.am	Fri Nov 20 03:46:10 2009 +0000
    25.3 @@ -38,6 +38,10 @@
    25.4  endif
    25.5  endif
    25.6  
    25.7 +if ENABLE_VDPAU
    25.8 +vdpau_module = xineplug_vo_out_vdpau.la
    25.9 +endif
   25.10 +
   25.11  if ENABLE_XCB
   25.12  XCBOSD = xcbosd.c
   25.13  if ENABLE_XCBSHM
   25.14 @@ -109,9 +113,14 @@
   25.15  		  $(xxmc_module) \
   25.16  		  $(xcbshm_module) \
   25.17  		  $(xcbxv_module) \
   25.18 +		  $(vdpau_module) \
   25.19                    xineplug_vo_out_raw.la \
   25.20                    xineplug_vo_out_none.la
   25.21  
   25.22 +xineplug_vo_out_vdpau_la_SOURCES = video_out_vdpau.c
   25.23 +xineplug_vo_out_vdpau_la_LIBADD = libyuv2rgb.la $(XINE_LIB) $(MLIB_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) -lvdpau
   25.24 +xineplug_vo_out_vdpau_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(X_CFLAGS)
   25.25 +
   25.26  xineplug_vo_out_xcbshm_la_SOURCES = video_out_xcbshm.c $(XCBOSD)
   25.27  xineplug_vo_out_xcbshm_la_LIBADD = libyuv2rgb.la $(XINE_LIB) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL) $(AVUTIL_LIBS)
   25.28  xineplug_vo_out_xcbshm_la_CFLAGS = $(AM_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS) $(AVUTIL_CFLAGS)
    26.1 --- a/src/video_out/video_out_raw.c	Thu Nov 19 15:29:17 2009 +0000
    26.2 +++ b/src/video_out/video_out_raw.c	Fri Nov 20 03:46:10 2009 +0000
    26.3 @@ -166,11 +166,16 @@
    26.4      clr = rle->color;
    26.5      alpha = trans[clr];
    26.6      for ( i=0; i<rlelen; ++i ) {
    26.7 -    	rgba[0] = colors[clr].y;
    26.8 -    	rgba[1] = colors[clr].cr;
    26.9 -    	rgba[2] = colors[clr].cb;
   26.10 -    	rgba[3] = alpha*255/15;
   26.11 -    	rgba+= 4;
   26.12 +      if ( alpha == 0 ) {
   26.13 +        rgba[0] = rgba[1] = rgba[2] = rgba[3] = 0;
   26.14 +      }
   26.15 +      else {
   26.16 +        rgba[0] = colors[clr].y;
   26.17 +        rgba[1] = colors[clr].cr;
   26.18 +        rgba[2] = colors[clr].cb;
   26.19 +        rgba[3] = alpha*255/15;
   26.20 +      }
   26.21 +      rgba+= 4;
   26.22      	++pos;
   26.23      }
   26.24      ++rle;
   26.25 @@ -300,6 +305,9 @@
   26.26    if (!frame)
   26.27      return NULL;
   26.28  
   26.29 +  frame->vo_frame.base[0] = frame->vo_frame.base[1] = frame->vo_frame.base[2] = frame->rgb = NULL;
   26.30 +  frame->width = frame->height = frame->format = frame->flags = 0;
   26.31 +
   26.32    pthread_mutex_init (&frame->vo_frame.mutex, NULL);
   26.33  
   26.34    /*
   26.35 @@ -333,8 +341,6 @@
   26.36        || (frame->flags  != flags)) {
   26.37  /*     lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */
   26.38  
   26.39 -    flags &= VO_BOTH_FIELDS;
   26.40 -
   26.41      /* (re-) allocate render space */
   26.42      av_free (frame->vo_frame.base[0]);
   26.43      av_free (frame->vo_frame.base[1]);
   26.44 @@ -357,7 +363,7 @@
   26.45      frame->rgb = av_mallocz (BYTES_PER_PIXEL*width*height);
   26.46  
   26.47      /* set up colorspace converter */
   26.48 -    switch (flags) {
   26.49 +    switch (flags & VO_BOTH_FIELDS) {
   26.50      case VO_TOP_FIELD:
   26.51      case VO_BOTTOM_FIELD:
   26.52        frame->yuv2rgb->configure (frame->yuv2rgb,
   26.53 @@ -384,6 +390,7 @@
   26.54      frame->width = width;
   26.55      frame->height = height;
   26.56      frame->format = format;
   26.57 +    frame->flags = flags;
   26.58  
   26.59      raw_frame_field ((vo_frame_t *)frame, flags);
   26.60    }
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/src/video_out/video_out_vdpau.c	Fri Nov 20 03:46:10 2009 +0000
    27.3 @@ -0,0 +1,2650 @@
    27.4 +/*
    27.5 + * Copyright (C) 2008 the xine project
    27.6 + * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
    27.7 + *
    27.8 + * This file is part of xine, a free video player.
    27.9 + *
   27.10 + * xine is free software; you can redistribute it and/or modify
   27.11 + * it under the terms of the GNU General Public License as published by
   27.12 + * the Free Software Foundation; either version 2 of the License, or
   27.13 + * (at your option) any later version.
   27.14 + *
   27.15 + * xine is distributed in the hope that it will be useful,
   27.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.18 + * GNU General Public License for more details.
   27.19 + *
   27.20 + * You should have received a copy of the GNU General Public License
   27.21 + * along with this program; if not, write to the Free Software
   27.22 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
   27.23 + *
   27.24 + *
   27.25 + * video_out_vdpau.c, a video output plugin
   27.26 + * using VDPAU (Video Decode and Presentation Api for Unix)
   27.27 + *
   27.28 + *
   27.29 + */
   27.30 +
   27.31 +/* #define LOG */
   27.32 +#define LOG_MODULE "video_out_vdpau"
   27.33 +
   27.34 +#ifdef HAVE_CONFIG_H
   27.35 +#include "config.h"
   27.36 +#endif
   27.37 +
   27.38 +#include <stdio.h>
   27.39 +#include <stdlib.h>
   27.40 +#include <unistd.h>
   27.41 +#include <string.h>
   27.42 +#include <math.h>
   27.43 +#include <errno.h>
   27.44 +#include <ctype.h>
   27.45 +#include <pthread.h>
   27.46 +
   27.47 +#include <xine.h>
   27.48 +#include <xine/video_out.h>
   27.49 +#include <xine/vo_scale.h>
   27.50 +#include <xine/xine_internal.h>
   27.51 +#include <xine/xineutils.h>
   27.52 +#include "yuv2rgb.h"
   27.53 +
   27.54 +#include <vdpau/vdpau_x11.h>
   27.55 +#include "accel_vdpau.h"
   27.56 +
   27.57 +#ifdef HAVE_FFMPEG_AVUTIL_H
   27.58 +#  include <mem.h>
   27.59 +#else
   27.60 +#  include <libavutil/mem.h>
   27.61 +#endif
   27.62 +
   27.63 +#define NUM_FRAMES_BACK 1
   27.64 +
   27.65 +#define LOCKDISPLAY /*define this if you have a buggy libX11/xcb*/
   27.66 +
   27.67 +
   27.68 +#define DEINT_BOB                    1
   27.69 +#define DEINT_HALF_TEMPORAL          2
   27.70 +#define DEINT_HALF_TEMPORAL_SPATIAL  3
   27.71 +#define DEINT_TEMPORAL               4
   27.72 +#define DEINT_TEMPORAL_SPATIAL       5
   27.73 +
   27.74 +#define NUMBER_OF_DEINTERLACERS 5
   27.75 +
   27.76 +char *vdpau_deinterlacer_name[] = {
   27.77 +  "bob",
   27.78 +  "half temporal",
   27.79 +  "half temporal_spatial",
   27.80 +  "temporal",
   27.81 +  "temporal_spatial",
   27.82 +  NULL
   27.83 +};
   27.84 +
   27.85 +char* vdpau_deinterlacer_description [] = {
   27.86 +  "bob\nBasic deinterlacing, doing 50i->50p.\n\n",
   27.87 +  "half temporal\nDisplays first field only, doing 50i->25p\n\n",
   27.88 +  "half temporal_spatial\nDisplays first field only, doing 50i->25p\n\n",
   27.89 +  "temporal\nVery good, 50i->50p\n\n",
   27.90 +  "temporal_spatial\nThe best, but very GPU intensive.\n\n",
   27.91 +  NULL
   27.92 +};
   27.93 +
   27.94 +
   27.95 +VdpOutputSurfaceRenderBlendState blend = {
   27.96 +  VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION,
   27.97 +  VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
   27.98 +  VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
   27.99 +  VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
  27.100 +  VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
  27.101 +  VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
  27.102 +  VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
  27.103 +  0
  27.104 +};
  27.105 +
  27.106 +
  27.107 +
  27.108 +VdpDevice vdp_device;
  27.109 +VdpPresentationQueue vdp_queue;
  27.110 +VdpPresentationQueueTarget vdp_queue_target;
  27.111 +
  27.112 +VdpDeviceDestroy *vdp_device_destroy;
  27.113 +
  27.114 +VdpGetProcAddress *vdp_get_proc_address;
  27.115 +
  27.116 +VdpGetApiVersion *vdp_get_api_version;
  27.117 +VdpGetInformationString *vdp_get_information_string;
  27.118 +VdpGetErrorString *vdp_get_error_string;
  27.119 +
  27.120 +VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_get_put_bits_ycbcr_capabilities;
  27.121 +VdpVideoSurfaceCreate *vdp_video_surface_create;
  27.122 +VdpVideoSurfaceDestroy *vdp_video_surface_destroy;
  27.123 +VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_putbits_ycbcr;
  27.124 +VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_getbits_ycbcr;
  27.125 +
  27.126 +VdpOutputSurfaceCreate *vdp_output_surface_create;
  27.127 +VdpOutputSurfaceDestroy *vdp_output_surface_destroy;
  27.128 +VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface;
  27.129 +VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits;
  27.130 +
  27.131 +VdpVideoMixerCreate *vdp_video_mixer_create;
  27.132 +VdpVideoMixerDestroy *vdp_video_mixer_destroy;
  27.133 +VdpVideoMixerRender *vdp_video_mixer_render;
  27.134 +VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values;
  27.135 +VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables;
  27.136 +VdpVideoMixerGetFeatureEnables *vdp_video_mixer_get_feature_enables;
  27.137 +VdpVideoMixerQueryFeatureSupport *vdp_video_mixer_query_feature_support;
  27.138 +VdpVideoMixerQueryParameterSupport *vdp_video_mixer_query_parameter_support;
  27.139 +VdpVideoMixerQueryAttributeSupport *vdp_video_mixer_query_attribute_support;
  27.140 +VdpVideoMixerQueryParameterValueRange *vdp_video_mixer_query_parameter_value_range;
  27.141 +VdpVideoMixerQueryAttributeValueRange *vdp_video_mixer_query_attribute_value_range;
  27.142 +
  27.143 +VdpGenerateCSCMatrix *vdp_generate_csc_matrix;
  27.144 +
  27.145 +VdpPresentationQueueTargetCreateX11 *vdp_queue_target_create_x11;
  27.146 +VdpPresentationQueueTargetDestroy *vdp_queue_target_destroy;
  27.147 +VdpPresentationQueueCreate *vdp_queue_create;
  27.148 +VdpPresentationQueueDestroy *vdp_queue_destroy;
  27.149 +VdpPresentationQueueDisplay *vdp_queue_display;
  27.150 +VdpPresentationQueueBlockUntilSurfaceIdle *vdp_queue_block;
  27.151 +VdpPresentationQueueSetBackgroundColor *vdp_queue_set_background_color;
  27.152 +VdpPresentationQueueGetTime *vdp_queue_get_time;
  27.153 +VdpPresentationQueueQuerySurfaceStatus *vdp_queue_query_surface_status;
  27.154 +
  27.155 +VdpBitmapSurfacePutBitsNative *vdp_bitmap_put_bits;
  27.156 +VdpBitmapSurfaceCreate  *vdp_bitmap_create;
  27.157 +VdpBitmapSurfaceDestroy *vdp_bitmap_destroy;
  27.158 +
  27.159 +VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities;
  27.160 +VdpDecoderCreate *vdp_decoder_create;
  27.161 +VdpDecoderDestroy *vdp_decoder_destroy;
  27.162 +VdpDecoderRender *vdp_decoder_render;
  27.163 +
  27.164 +VdpPreemptionCallbackRegister *vdp_preemption_callback_register;
  27.165 +
  27.166 +static void vdp_preemption_callback( VdpDevice device, void *context );
  27.167 +static void vdpau_reinit( vo_driver_t *this_gen );
  27.168 +
  27.169 +static VdpVideoSurfaceCreate *orig_vdp_video_surface_create;
  27.170 +static VdpVideoSurfaceDestroy *orig_vdp_video_surface_destroy;
  27.171 +
  27.172 +static VdpDecoderCreate *orig_vdp_decoder_create;
  27.173 +static VdpDecoderDestroy *orig_vdp_decoder_destroy;
  27.174 +static VdpDecoderRender *orig_vdp_decoder_render;
  27.175 +
  27.176 +static Display *guarded_display;
  27.177 +
  27.178 +static VdpStatus guarded_vdp_video_surface_create(VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height,VdpVideoSurface *surface)
  27.179 +{
  27.180 +  VdpStatus r;
  27.181 +#ifdef LOCKDISPLAY
  27.182 +  XLockDisplay(guarded_display);
  27.183 +#endif
  27.184 +  r = orig_vdp_video_surface_create(device, chroma_type, width, height, surface);
  27.185 +#ifdef LOCKDISPLAY
  27.186 +  XUnlockDisplay(guarded_display);
  27.187 +#endif
  27.188 +  return r;
  27.189 +}
  27.190 +
  27.191 +static VdpStatus guarded_vdp_video_surface_destroy(VdpVideoSurface surface)
  27.192 +{
  27.193 +  VdpStatus r;
  27.194 +  /*XLockDisplay(guarded_display);*/
  27.195 +  r = orig_vdp_video_surface_destroy(surface);
  27.196 +  /*XUnlockDisplay(guarded_display);*/
  27.197 +  return r;
  27.198 +}
  27.199 +
  27.200 +static VdpStatus guarded_vdp_decoder_create(VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder)
  27.201 +{
  27.202 +  VdpStatus r;
  27.203 +#ifdef LOCKDISPLAY
  27.204 +  XLockDisplay(guarded_display);
  27.205 +#endif
  27.206 +  r = orig_vdp_decoder_create(device, profile, width, height, max_references, decoder);
  27.207 +#ifdef LOCKDISPLAY
  27.208 +  XUnlockDisplay(guarded_display);
  27.209 +#endif
  27.210 +  return r;
  27.211 +}
  27.212 +
  27.213 +static VdpStatus guarded_vdp_decoder_destroy(VdpDecoder decoder)
  27.214 +{
  27.215 +  VdpStatus r;
  27.216 +#ifdef LOCKDISPLAY
  27.217 +  XLockDisplay(guarded_display);
  27.218 +#endif
  27.219 +  r = orig_vdp_decoder_destroy(decoder);
  27.220 +#ifdef LOCKDISPLAY
  27.221 +  XUnlockDisplay(guarded_display);
  27.222 +#endif
  27.223 +  return r;
  27.224 +}
  27.225 +
  27.226 +static VdpStatus guarded_vdp_decoder_render(VdpDecoder decoder, VdpVideoSurface target, VdpPictureInfo const *picture_info, uint32_t bitstream_buffer_count, VdpBitstreamBuffer const *bitstream_buffers)
  27.227 +{
  27.228 +  VdpStatus r;
  27.229 +#ifdef LOCKDISPLAY
  27.230 +  XLockDisplay(guarded_display);
  27.231 +#endif
  27.232 +  r = orig_vdp_decoder_render(decoder, target, picture_info, bitstream_buffer_count, bitstream_buffers);
  27.233 +#ifdef LOCKDISPLAY
  27.234 +  XUnlockDisplay(guarded_display);
  27.235 +#endif
  27.236 +  return r;
  27.237 +}
  27.238 +
  27.239 +
  27.240 +
  27.241 +typedef struct {
  27.242 +  VdpBitmapSurface ovl_bitmap;
  27.243 +  uint32_t  bitmap_width, bitmap_height;
  27.244 +  int ovl_w, ovl_h; /* overlay's width and height */
  27.245 +  int ovl_x, ovl_y; /* overlay's top-left display position */
  27.246 +  int unscaled;
  27.247 +  int expected_overlay_width; /*if >0 scale to video width*/
  27.248 +  int expected_overlay_height; /* if >0 scale to video height */
  27.249 +} vdpau_overlay_t;
  27.250 +
  27.251 +
  27.252 +typedef struct {
  27.253 +  int                 x;
  27.254 +  int                 y;
  27.255 +  int                 w;
  27.256 +  int                 h;
  27.257 +}
  27.258 +argb_ovl_data_t;
  27.259 +
  27.260 +
  27.261 +typedef struct {
  27.262 +  vo_frame_t         vo_frame;
  27.263 +
  27.264 +  int                width, height, format, flags;
  27.265 +  double             ratio;
  27.266 +
  27.267 +  vdpau_accel_t     vdpau_accel_data;
  27.268 +} vdpau_frame_t;
  27.269 +
  27.270 +
  27.271 +typedef struct {
  27.272 +
  27.273 +  vo_driver_t        vo_driver;
  27.274 +  vo_scale_t         sc;
  27.275 +
  27.276 +  Display           *display;
  27.277 +  int                screen;
  27.278 +  Drawable           drawable;
  27.279 +
  27.280 +  config_values_t   *config;
  27.281 +
  27.282 +  int ovl_changed;
  27.283 +  vdpau_overlay_t     overlays[XINE_VORAW_MAX_OVL];
  27.284 +  yuv2rgb_factory_t   *yuv2rgb_factory;
  27.285 +  yuv2rgb_t           *ovl_yuv2rgb;
  27.286 +  VdpOutputSurface    overlay_output;
  27.287 +  uint32_t            overlay_output_width;
  27.288 +  uint32_t            overlay_output_height;
  27.289 +  int                 has_overlay;
  27.290 +
  27.291 +  VdpOutputSurface    overlay_unscaled;
  27.292 +  uint32_t            overlay_unscaled_width;
  27.293 +  uint32_t            overlay_unscaled_height;
  27.294 +  int                 has_unscaled;
  27.295 +
  27.296 +  VdpOutputSurface    argb_overlay;
  27.297 +  uint32_t            argb_overlay_width;
  27.298 +  uint32_t            argb_overlay_height;
  27.299 +  int                 has_argb_overlay;
  27.300 +  int                 argb_ovl_count;
  27.301 +  vo_overlay_t       *argb_ovl[XINE_VORAW_MAX_OVL];
  27.302 +  int                 argb_ovl_data_count;
  27.303 +  argb_ovl_data_t     argb_ovl_data[XINE_VORAW_MAX_OVL];
  27.304 +
  27.305 +  int32_t             video_window_x;
  27.306 +  int32_t             video_window_y;
  27.307 +  int32_t             video_window_width;
  27.308 +  int32_t             video_window_height;
  27.309 +
  27.310 +  VdpVideoSurface      soft_surface;
  27.311 +  uint32_t             soft_surface_width;
  27.312 +  uint32_t             soft_surface_height;
  27.313 +  int                  soft_surface_format;
  27.314 +
  27.315 +#define NOUTPUTSURFACE 2
  27.316 +  VdpOutputSurface     output_surface[NOUTPUTSURFACE];
  27.317 +  uint8_t              current_output_surface;
  27.318 +  uint32_t             output_surface_width[NOUTPUTSURFACE];
  27.319 +  uint32_t             output_surface_height[NOUTPUTSURFACE];
  27.320 +  uint8_t              init_queue;
  27.321 +
  27.322 +  VdpVideoMixer        video_mixer;
  27.323 +  VdpChromaType        video_mixer_chroma;
  27.324 +  uint32_t             video_mixer_width;
  27.325 +  uint32_t             video_mixer_height;
  27.326 +  VdpColorStandard     color_standard;
  27.327 +  VdpBool              temporal_spatial_is_supported;
  27.328 +  VdpBool              temporal_is_supported;
  27.329 +  VdpBool              noise_reduction_is_supported;
  27.330 +  VdpBool              sharpness_is_supported;
  27.331 +  VdpBool              inverse_telecine_is_supported;
  27.332 +  VdpBool              skip_chroma_is_supported;
  27.333 +
  27.334 +  char*                deinterlacers_name[NUMBER_OF_DEINTERLACERS+1];
  27.335 +  int                  deinterlacers_method[NUMBER_OF_DEINTERLACERS];
  27.336 +
  27.337 +  int                  scaling_level_max;
  27.338 +  int                  scaling_level_current;
  27.339 +
  27.340 +  VdpColor             back_color;
  27.341 +
  27.342 +  vdpau_frame_t        *back_frame[ NUM_FRAMES_BACK ];
  27.343 +
  27.344 +  uint32_t          capabilities;
  27.345 +  xine_t            *xine;
  27.346 +
  27.347 +  int               hue;
  27.348 +  int               saturation;
  27.349 +  int               brightness;
  27.350 +  int               contrast;
  27.351 +  int               sharpness;
  27.352 +  int               noise;
  27.353 +  int               deinterlace;
  27.354 +  int               deinterlace_method;
  27.355 +  int               enable_inverse_telecine;
  27.356 +  int               honor_progressive;
  27.357 +  int               skip_chroma;
  27.358 +
  27.359 +  int               vdp_runtime_nr;
  27.360 +  int               reinit_needed;
  27.361 +
  27.362 +  int               allocated_surfaces;
  27.363 +  int		            zoom_x;
  27.364 +  int		            zoom_y;
  27.365 +} vdpau_driver_t;
  27.366 +
  27.367 +
  27.368 +typedef struct {
  27.369 +  video_driver_class_t driver_class;
  27.370 +  xine_t              *xine;
  27.371 +} vdpau_class_t;
  27.372 +
  27.373 +
  27.374 +
  27.375 +static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t  *this, vo_overlay_t *overlay, vdpau_frame_t *frame)
  27.376 +{
  27.377 +  int i;
  27.378 +  clut_t* clut = (clut_t*) overlay->color;
  27.379 +
  27.380 +  if (!overlay->rgb_clut) {
  27.381 +    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++ ) {
  27.382 +      *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);
  27.383 +    }
  27.384 +    overlay->rgb_clut++;
  27.385 +  }
  27.386 +  if (!overlay->hili_rgb_clut) {
  27.387 +    clut = (clut_t*) overlay->hili_color;
  27.388 +    for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
  27.389 +      *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr);
  27.390 +    }
  27.391 +    overlay->hili_rgb_clut++;
  27.392 +  }
  27.393 +}
  27.394 +
  27.395 +
  27.396 +
  27.397 +static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_gen)
  27.398 +{
  27.399 +  vdpau_driver_t  *this = (vdpau_driver_t *) this_gen;
  27.400 +  int i, k;
  27.401 +
  27.402 +  vo_overlay_t *ovl[XINE_VORAW_MAX_OVL];
  27.403 +  argb_ovl_data_t ovl_data[XINE_VORAW_MAX_OVL];
  27.404 +  int ovl_data_count = 0;
  27.405 +
  27.406 +  int total_extent_width = 0, total_extent_height = 0;
  27.407 +  this->video_window_x      = 0;
  27.408 +  this->video_window_y      = 0;
  27.409 +  this->video_window_width  = 0;
  27.410 +  this->video_window_height = 0;
  27.411 +
  27.412 +  /* lock layers while processing and determine extent */
  27.413 +  for (i = 0; i < this->argb_ovl_count; i++) {
  27.414 +    pthread_mutex_lock(&this->argb_ovl[i]->argb_layer->mutex);
  27.415 +
  27.416 +    if (this->argb_ovl[i]->argb_layer->buffer != NULL) {
  27.417 +      int extent_width  = this->argb_ovl[i]->extent_width;
  27.418 +      int extent_height = this->argb_ovl[i]->extent_height;
  27.419 +      if (extent_width <= 0 || extent_height <= 0) {
  27.420 +        extent_width  = frame_gen->width;
  27.421 +        extent_height = frame_gen->height;
  27.422 +      }
  27.423 +      if (extent_width > 0 && extent_height > 0) {
  27.424 +        if (total_extent_width < extent_width)
  27.425 +          total_extent_width = extent_width;
  27.426 +        if (total_extent_height < extent_height)
  27.427 +          total_extent_height = extent_height;
  27.428 +        ovl_data[ovl_data_count].x = this->argb_ovl[i]->x;
  27.429 +        ovl_data[ovl_data_count].y = this->argb_ovl[i]->y;
  27.430 +        ovl_data[ovl_data_count].w = this->argb_ovl[i]->width;
  27.431 +        ovl_data[ovl_data_count].h = this->argb_ovl[i]->height;
  27.432 +        ovl[ovl_data_count++] = this->argb_ovl[i];
  27.433 +      }
  27.434 +      if (this->argb_ovl[i]->video_window_width > 0
  27.435 +        && this->argb_ovl[i]->video_window_height > 0) {
  27.436 +        /* last one wins */
  27.437 +        this->video_window_x      = this->argb_ovl[i]->video_window_x;
  27.438 +        this->video_window_y      = this->argb_ovl[i]->video_window_y;
  27.439 +        this->video_window_width  = this->argb_ovl[i]->video_window_width;
  27.440 +        this->video_window_height = this->argb_ovl[i]->video_window_height;
  27.441 +      }
  27.442 +    }
  27.443 +  }
  27.444 +
  27.445 +  /* adjust surface */
  27.446 +  if (total_extent_width > 0 && total_extent_height > 0) {
  27.447 +    if (this->argb_overlay_width != total_extent_width || this->argb_overlay_height != total_extent_height || this->argb_overlay == VDP_INVALID_HANDLE) {
  27.448 +      if (this->argb_overlay != VDP_INVALID_HANDLE)
  27.449 +        vdp_output_surface_destroy(this->argb_overlay);
  27.450 +
  27.451 +      VdpStatus st = vdp_output_surface_create(vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, total_extent_width, total_extent_height, &this->argb_overlay);
  27.452 +      if (st != VDP_STATUS_OK)
  27.453 +        printf("vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st));
  27.454 +
  27.455 +      this->argb_overlay_width  = total_extent_width;
  27.456 +      this->argb_overlay_height = total_extent_height;
  27.457 +
  27.458 +      /* change argb_ovl_data to wipe complete surface */
  27.459 +      this->argb_ovl_data_count = 1;
  27.460 +      this->argb_ovl_data[0].x = 0;
  27.461 +      this->argb_ovl_data[0].y = 0;
  27.462 +      this->argb_ovl_data[0].w = total_extent_width;
  27.463 +      this->argb_ovl_data[0].h = total_extent_height;
  27.464 +
  27.465 +      /* extend dirty areas to maximum for filling wiped surface */
  27.466 +      for (i = 0; i < ovl_data_count; i++) {
  27.467 +        ovl[i]->argb_layer->x1 = 0;
  27.468 +        ovl[i]->argb_layer->y1 = 0;
  27.469 +        ovl[i]->argb_layer->x2 = ovl[i]->width;
  27.470 +        ovl[i]->argb_layer->y2 = ovl[i]->height;
  27.471 +      }
  27.472 +    }
  27.473 +  }
  27.474 +
  27.475 +  /* wipe surface for gone overlays */
  27.476 +  if (this->argb_overlay != VDP_INVALID_HANDLE) {
  27.477 +    uint32_t *zeros = NULL;
  27.478 +    for (i = 0; i < this->argb_ovl_data_count; i++) {
  27.479 +      argb_ovl_data_t *curr_ovl_data = &this->argb_ovl_data[i];
  27.480 +      int ovl_gone = 1;
  27.481 +      for (k = 0; k < ovl_data_count; k++) {
  27.482 +        if (0 == memcmp(curr_ovl_data, &ovl_data[k], sizeof (*curr_ovl_data))) {
  27.483 +          ovl_gone = 0;
  27.484 +          break;
  27.485 +        }
  27.486 +      }
  27.487 +      if (!ovl_gone)
  27.488 +        continue;
  27.489 +      if (!zeros)
  27.490 +        zeros = calloc(4, this->argb_overlay_width * this->argb_overlay_height);
  27.491 +      if (zeros) {
  27.492 +        uint32_t pitch = curr_ovl_data->w * 4;
  27.493 +        VdpRect dest = { curr_ovl_data->x, curr_ovl_data->y, curr_ovl_data->x + curr_ovl_data->w, curr_ovl_data->y + curr_ovl_data->h };
  27.494 +        VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&zeros, &pitch, &dest);
  27.495 +        if (st != VDP_STATUS_OK)
  27.496 +          printf("vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st));
  27.497 +      }
  27.498 +    }
  27.499 +    free(zeros);
  27.500 +  }
  27.501 +
  27.502 +  /* set destination area according to dirty area of argb layer and reset dirty area */
  27.503 +  for (i = 0; i < ovl_data_count; i++) {
  27.504 +    uint32_t pitch = ovl[i]->width * 4;
  27.505 +    uint32_t *buffer_start = ovl[i]->argb_layer->buffer + ovl[i]->argb_layer->y1 * ovl[i]->width + ovl[i]->argb_layer->x1;
  27.506 +    VdpRect dest = { ovl[i]->x + ovl[i]->argb_layer->x1, ovl[i]->y + ovl[i]->argb_layer->y1, ovl[i]->x + ovl[i]->argb_layer->x2, ovl[i]->y + ovl[i]->argb_layer->y2 };
  27.507 +    ovl[i]->argb_layer->x1 = ovl[i]->width;
  27.508 +    ovl[i]->argb_layer->y1 = ovl[i]->height;
  27.509 +    ovl[i]->argb_layer->x2 = 0;
  27.510 +    ovl[i]->argb_layer->y2 = 0;
  27.511 +
  27.512 +    VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&buffer_start, &pitch, &dest);
  27.513 +    if (st != VDP_STATUS_OK)
  27.514 +      printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st));
  27.515 +    else
  27.516 +      this->has_argb_overlay = 1;
  27.517 +  }
  27.518 +
  27.519 +  /* store ovl_data */
  27.520 +  memcpy(this->argb_ovl_data, ovl_data, sizeof (ovl_data));
  27.521 +  this->argb_ovl_data_count = ovl_data_count;
  27.522 +
  27.523 +  /* unlock layers */
  27.524 +  for (i = 0; i < this->argb_ovl_count; i++)
  27.525 +    pthread_mutex_unlock(&this->argb_ovl[i]->argb_layer->mutex);
  27.526 +}
  27.527 +
  27.528 +
  27.529 +
  27.530 +static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay )
  27.531 +{
  27.532 +  vdpau_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1];
  27.533 +
  27.534 +  if ( overlay->width<=0 || overlay->height<=0 )
  27.535 +    return 0;
  27.536 +
  27.537 +  if ( (ovl->bitmap_width < overlay->width ) || (ovl->bitmap_height < overlay->height) || (ovl->ovl_bitmap == VDP_INVALID_HANDLE) ) {
  27.538 +    if (ovl->ovl_bitmap != VDP_INVALID_HANDLE) {
  27.539 +      vdp_bitmap_destroy( ovl->ovl_bitmap );
  27.540 +      ovl->ovl_bitmap = VDP_INVALID_HANDLE;
  27.541 +    }
  27.542 +    VdpStatus st = vdp_bitmap_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, 0, &ovl->ovl_bitmap );
  27.543 +    if ( st != VDP_STATUS_OK ) {
  27.544 +      printf( "vdpau_process_ovl: vdp_bitmap_create failed : %s\n", vdp_get_error_string(st) );
  27.545 +    }
  27.546 +    ovl->bitmap_width = overlay->width;
  27.547 +    ovl->bitmap_height = overlay->height;
  27.548 +  }
  27.549 +  ovl->ovl_w = overlay->width;
  27.550 +  ovl->ovl_h = overlay->height;
  27.551 +  ovl->ovl_x = overlay->x;
  27.552 +  ovl->ovl_y = overlay->y;
  27.553 +  ovl->unscaled = overlay->unscaled;
  27.554 +  ovl->expected_overlay_width = overlay->extent_width;
  27.555 +  ovl->expected_overlay_height = overlay->extent_height;
  27.556 +  uint32_t *buf = (uint32_t*)malloc(ovl->ovl_w*ovl->ovl_h*4);
  27.557 +  if ( !buf )
  27.558 +    return 0;
  27.559 +
  27.560 +  int num_rle = overlay->num_rle;
  27.561 +  rle_elem_t *rle = overlay->rle;
  27.562 +  uint32_t *rgba = buf;
  27.563 +  uint32_t red, green, blue, alpha;
  27.564 +  clut_t *low_colors = (clut_t*)overlay->color;
  27.565 +  clut_t *hili_colors = (clut_t*)overlay->hili_color;
  27.566 +  uint8_t *low_trans = overlay->trans;
  27.567 +  uint8_t *hili_trans = overlay->hili_trans;
  27.568 +  clut_t *colors;
  27.569 +  uint8_t *trans;
  27.570 +  int rlelen = 0;
  27.571 +  uint8_t clr = 0;
  27.572 +  int i, pos=0, x, y;
  27.573 +
  27.574 +  while ( num_rle>0 ) {
  27.575 +    x = pos%ovl->ovl_w;
  27.576 +    y = pos/ovl->ovl_w;
  27.577 +    if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) {
  27.578 +      colors = hili_colors;
  27.579 +      trans = hili_trans;
  27.580 +    }
  27.581 +    else {
  27.582 +      colors = low_colors;
  27.583 +      trans = low_trans;
  27.584 +    }
  27.585 +    rlelen = rle->len;
  27.586 +    clr = rle->color;
  27.587 +    for ( i=0; i<rlelen; ++i ) {
  27.588 +      if ( trans[clr] == 0 ) {
  27.589 +        alpha = red = green = blue = 0;
  27.590 +      }
  27.591 +      else {
  27.592 +        red = colors[clr].y; /* red */
  27.593 +        green = colors[clr].cr; /* green */
  27.594 +        blue = colors[clr].cb; /* blue */
  27.595 +        alpha = trans[clr]*255/15;
  27.596 +      }
  27.597 +      *rgba = (alpha<<24) | (red<<16) | (green<<8) | blue;
  27.598 +      rgba++;
  27.599 +      ++pos;
  27.600 +    }
  27.601 +    ++rle;
  27.602 +    --num_rle;
  27.603 +  }
  27.604 +  uint32_t pitch = ovl->ovl_w*4;
  27.605 +  VdpRect dest = { 0, 0, ovl->ovl_w, ovl->ovl_h };
  27.606 +  VdpStatus st = vdp_bitmap_put_bits( ovl->ovl_bitmap, &buf, &pitch, &dest);
  27.607 +  if ( st != VDP_STATUS_OK ) {
  27.608 +    printf( "vdpau_process_ovl: vdp_bitmap_put_bits failed : %s\n", vdp_get_error_string(st) );
  27.609 +  }
  27.610 +  free(buf);
  27.611 +  return 1;
  27.612 +}
  27.613 +
  27.614 +
  27.615 +
  27.616 +static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed)
  27.617 +{
  27.618 +  vdpau_driver_t  *this = (vdpau_driver_t *) this_gen;
  27.619 +
  27.620 +  if ( !changed )
  27.621 +    return;
  27.622 +
  27.623 +  this->has_overlay = this->has_unscaled = 0;
  27.624 +  this->has_argb_overlay = 0;
  27.625 +  this->argb_ovl_count = 0;
  27.626 +  ++this->ovl_changed;
  27.627 +}
  27.628 +
  27.629 +
  27.630 +
  27.631 +static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay)
  27.632 +{
  27.633 +  vdpau_driver_t  *this = (vdpau_driver_t *) this_gen;
  27.634 +  vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen;
  27.635 +
  27.636 +  if (!this->ovl_changed)
  27.637 +    return;
  27.638 +
  27.639 +  if (overlay->rle) {
  27.640 +    if (this->ovl_changed >= XINE_VORAW_MAX_OVL)
  27.641 +      return;
  27.642 +    if (!overlay->rgb_clut || !overlay->hili_rgb_clut)
  27.643 +      vdpau_overlay_clut_yuv2rgb (this, overlay, frame);
  27.644 +    if ( vdpau_process_ovl( this, overlay ) )
  27.645 +      ++this->ovl_changed;
  27.646 +  }
  27.647 +
  27.648 +  if (overlay->argb_layer) {
  27.649 +    if (this->argb_ovl_count >= XINE_VORAW_MAX_OVL)
  27.650 +      return;
  27.651 +    this->argb_ovl[this->argb_ovl_count++] = overlay;
  27.652 +  }
  27.653 +}
  27.654 +
  27.655 +
  27.656 +
  27.657 +static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame)
  27.658 +{
  27.659 +  vdpau_driver_t  *this = (vdpau_driver_t *) this_gen;
  27.660 +  int i;
  27.661 +  VdpStatus st;
  27.662 +
  27.663 +  if ( !this->ovl_changed )
  27.664 +    return;
  27.665 +
  27.666 +  if (this->argb_ovl_count || this->argb_ovl_data_count)
  27.667 +    vdpau_process_argb_ovls(this, frame);
  27.668 +
  27.669 +  if ( !(this->ovl_changed-1) ) {
  27.670 +    this->ovl_changed = 0;
  27.671 +    this->has_overlay = 0;
  27.672 +    this->has_unscaled = 0;
  27.673 +    return;
  27.674 +  }
  27.675 +
  27.676 +  int w=0, h=0;
  27.677 +  int scaler = 0;
  27.678 +  for ( i=0; i<this->ovl_changed-1; ++i ) {
  27.679 +    if ( this->overlays[i].unscaled )
  27.680 +      continue;
  27.681 +    if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) )
  27.682 +      w = this->overlays[i].ovl_x+this->overlays[i].ovl_w;
  27.683 +    if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) )
  27.684 +      h = this->overlays[i].ovl_y+this->overlays[i].ovl_h;
  27.685 +    if ( this->overlays[i].expected_overlay_width )
  27.686 +      scaler = 1;
  27.687 +    if ( this->overlays[i].expected_overlay_height )
  27.688 +      scaler = 1;
  27.689 +  }
  27.690 +
  27.691 +  if ( scaler ) {
  27.692 +    w = this->video_mixer_width;
  27.693 +    h = this->video_mixer_height;
  27.694 +  }
  27.695 +
  27.696 +  int out_w = (w>frame->width) ? w : frame->width;
  27.697 +  int out_h = (h>frame->height) ? h : frame->height;
  27.698 +
  27.699 +  if ( (this->overlay_output_width!=out_w || this->overlay_output_height!=out_h) && this->overlay_output != VDP_INVALID_HANDLE ) {
  27.700 +    st = vdp_output_surface_destroy( this->overlay_output );
  27.701 +    if ( st != VDP_STATUS_OK ) {
  27.702 +      printf( "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) );
  27.703 +    }
  27.704 +    this->overlay_output = VDP_INVALID_HANDLE;
  27.705 +  }
  27.706 +
  27.707 +  this->overlay_output_width = out_w;
  27.708 +  this->overlay_output_height = out_h;
  27.709 +
  27.710 +  w = 64; h = 64;
  27.711 +  for ( i=0; i<this->ovl_changed-1; ++i ) {
  27.712 +    if ( !this->overlays[i].unscaled )
  27.713 +      continue;
  27.714 +    if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) )
  27.715 +      w = this->overlays[i].ovl_x+this->overlays[i].ovl_w;
  27.716 +    if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) )
  27.717 +      h = this->overlays[i].ovl_y+this->overlays[i].ovl_h;
  27.718 +  }
  27.719 +
  27.720 +  if ( (this->overlay_unscaled_width!=w || this->overlay_unscaled_height!=h) && this->overlay_unscaled != VDP_INVALID_HANDLE ) {
  27.721 +    st = vdp_output_surface_destroy( this->overlay_unscaled );
  27.722 +    if ( st != VDP_STATUS_OK ) {
  27.723 +      printf( "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) );
  27.724 +    }
  27.725 +    this->overlay_unscaled = VDP_INVALID_HANDLE;
  27.726 +  }
  27.727 +
  27.728 +  this->overlay_unscaled_width = w;
  27.729 +  this->overlay_unscaled_height = h;
  27.730 +
  27.731 +  if ( this->overlay_unscaled == VDP_INVALID_HANDLE ) {
  27.732 +    st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_unscaled_width, this->overlay_unscaled_height, &this->overlay_unscaled );
  27.733 +    if ( st != VDP_STATUS_OK )
  27.734 +      printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) );
  27.735 +  }
  27.736 +
  27.737 +  if ( this->overlay_output == VDP_INVALID_HANDLE ) {
  27.738 +    st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_output_width, this->overlay_output_height, &this->overlay_output );
  27.739 +    if ( st != VDP_STATUS_OK )
  27.740 +      printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) );
  27.741 +  }
  27.742 +
  27.743 +  w = (this->overlay_unscaled_width>this->overlay_output_width) ? this->overlay_unscaled_width : this->overlay_output_width;
  27.744 +  h = (this->overlay_unscaled_height>this->overlay_output_height) ? this->overlay_unscaled_height : this->overlay_output_height;
  27.745 +
  27.746 +  uint32_t *buf = (uint32_t*)calloc(w*4,h);
  27.747 +  uint32_t pitch = w*4;
  27.748 +  VdpRect clear = { 0, 0, this->overlay_output_width, this->overlay_output_height };
  27.749 +  st = vdp_output_surface_put_bits( this->overlay_output, &buf, &pitch, &clear );
  27.750 +  if ( st != VDP_STATUS_OK ) {
  27.751 +    printf( "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) );
  27.752 +  }
  27.753 +  clear.x1 = this->overlay_unscaled_width; clear.y1 = this->overlay_unscaled_height;
  27.754 +  st = vdp_output_surface_put_bits( this->overlay_unscaled, &buf, &pitch, &clear );
  27.755 +  if ( st != VDP_STATUS_OK ) {
  27.756 +    printf( "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) );
  27.757 +  }
  27.758 +  free(buf);
  27.759 +
  27.760 +  VdpOutputSurface *surface;
  27.761 +  for ( i=0; i<this->ovl_changed-1; ++i ) {
  27.762 +    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 };
  27.763 +    if ( this->overlays[i].expected_overlay_width ) {
  27.764 +      double rx = (double)this->overlay_output_width/(double)this->overlays[i].expected_overlay_width;
  27.765 +      double ry = (double)this->overlay_output_height/(double)this->overlays[i].expected_overlay_height;
  27.766 +      dest.x0 *= rx; dest.y0 *= ry; dest.x1 *=rx; dest.y1 *= ry;
  27.767 +      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 );
  27.768 +    }
  27.769 +    VdpRect src = { 0, 0, this->overlays[i].ovl_w, this->overlays[i].ovl_h };
  27.770 +    surface = (this->overlays[i].unscaled) ? &this->overlay_unscaled : &this->overlay_output;
  27.771 +    st = vdp_output_surface_render_bitmap_surface( *surface, &dest, this->overlays[i].ovl_bitmap, &src, 0, &blend, 0 );
  27.772 +    if ( st != VDP_STATUS_OK ) {
  27.773 +      printf( "vdpau_overlay_end: vdp_output_surface_render_bitmap_surface failed : %s\n", vdp_get_error_string(st) );
  27.774 +    }
  27.775 +  }
  27.776 +  this->has_overlay = 1;
  27.777 +  this->ovl_changed = 0;
  27.778 +}
  27.779 +
  27.780 +
  27.781 +
  27.782 +static void vdpau_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src)
  27.783 +{
  27.784 +  vdpau_frame_t  *frame = (vdpau_frame_t *) vo_img ;
  27.785 +
  27.786 +  vo_img->proc_called = 1;
  27.787 +}
  27.788 +
  27.789 +
  27.790 +
  27.791 +static void vdpau_frame_field (vo_frame_t *vo_img, int which_field)
  27.792 +{
  27.793 +}
  27.794 +
  27.795 +
  27.796 +
  27.797 +static void vdpau_frame_dispose (vo_frame_t *vo_img)
  27.798 +{
  27.799 +  vdpau_frame_t  *frame = (vdpau_frame_t *) vo_img ;
  27.800 +
  27.801 +  av_free (frame->vo_frame.base[0]);
  27.802 +  av_free (frame->vo_frame.base[1]);
  27.803 +  av_free (frame->vo_frame.base[2]);
  27.804 +  if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE )
  27.805 +    vdp_video_surface_destroy( frame->vdpau_accel_data.surface );
  27.806 +  free (frame);
  27.807 +}
  27.808 +
  27.809 +
  27.810 +
  27.811 +static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen)
  27.812 +{
  27.813 +  vdpau_frame_t  *frame;
  27.814 +  vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
  27.815 +
  27.816 +  lprintf( "vo_vdpau: vdpau_alloc_frame\n" );
  27.817 +
  27.818 +  frame = (vdpau_frame_t *) calloc(1, sizeof(vdpau_frame_t));
  27.819 +
  27.820 +  if (!frame)
  27.821 +    return NULL;
  27.822 +
  27.823 +  frame->vo_frame.base[0] = frame->vo_frame.base[1] = frame->vo_frame.base[2] = NULL;
  27.824 +  frame->width = frame->height = frame->format = frame->flags = 0;
  27.825 +
  27.826 +  frame->vo_frame.accel_data = &frame->vdpau_accel_data;
  27.827 +
  27.828 +  pthread_mutex_init (&frame->vo_frame.mutex, NULL);
  27.829 +
  27.830 +  /*
  27.831 +   * supply required functions/fields
  27.832 +   */
  27.833 +  frame->vo_frame.proc_duplicate_frame_data = NULL;
  27.834 +  frame->vo_frame.proc_slice = vdpau_frame_proc_slice;
  27.835 +  frame->vo_frame.proc_frame = NULL;
  27.836 +  frame->vo_frame.field      = vdpau_frame_field;
  27.837 +  frame->vo_frame.dispose    = vdpau_frame_dispose;
  27.838 +  frame->vo_frame.driver     = this_gen;
  27.839 +
  27.840 +  frame->vdpau_accel_data.vo_frame = &frame->vo_frame;
  27.841 +  frame->vdpau_accel_data.vdp_device = vdp_device;
  27.842 +  frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE;
  27.843 +  frame->vdpau_accel_data.chroma = VDP_CHROMA_TYPE_420;
  27.844 +  frame->vdpau_accel_data.color_standard = this->color_standard;
  27.845 +  frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create;
  27.846 +  frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy;
  27.847 +  frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render;
  27.848 +  frame->vdpau_accel_data.vdp_get_error_string = vdp_get_error_string;
  27.849 +  frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr;
  27.850 +  frame->vdpau_accel_data.current_vdp_runtime_nr = &this->vdp_runtime_nr;
  27.851 +
  27.852 +  return (vo_frame_t *) frame;
  27.853 +}
  27.854 +
  27.855 +
  27.856 +
  27.857 +static void vdpau_provide_standard_frame_data (vo_frame_t *this_gen, xine_current_frame_data_t *data)
  27.858 +{
  27.859 +  vdpau_frame_t *this = (vdpau_frame_t *)this_gen;
  27.860 +  VdpStatus st;
  27.861 +  VdpYCbCrFormat format;
  27.862 +
  27.863 +  if (this->vo_frame.format != XINE_IMGFMT_VDPAU) {
  27.864 +    fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->vo_frame.format);
  27.865 +    return;
  27.866 +  }
  27.867 +
  27.868 +  if (!(this->flags & VO_CHROMA_422)) {
  27.869 +    data->format = XINE_IMGFMT_YV12;
  27.870 +    data->img_size = this->vo_frame.width * this->vo_frame.height
  27.871 +                   + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2)
  27.872 +                   + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2);
  27.873 +    if (data->img) {
  27.874 +      this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 7) / 8);
  27.875 +      this->vo_frame.pitches[1] = 8*((this->vo_frame.width + 15) / 16);
  27.876 +      this->vo_frame.pitches[2] = 8*((this->vo_frame.width + 15) / 16);
  27.877 +      this->vo_frame.base[0] = av_mallocz(this->vo_frame.pitches[0] * this->vo_frame.height);
  27.878 +      this->vo_frame.base[1] = av_mallocz(this->vo_frame.pitches[1] * ((this->vo_frame.height+1)/2));
  27.879 +      this->vo_frame.base[2] = av_mallocz(this->vo_frame.pitches[2] * ((this->vo_frame.height+1)/2));
  27.880 +      format = VDP_YCBCR_FORMAT_YV12;
  27.881 +    }
  27.882 +  } else {
  27.883 +    data->format = XINE_IMGFMT_YUY2;
  27.884 +    data->img_size = this->vo_frame.width * this->vo_frame.height
  27.885 +                   + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height
  27.886 +                   + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height;
  27.887 +    if (data->img) {
  27.888 +      this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 3) / 4);
  27.889 +      this->vo_frame.base[0] = av_mallocz(this->vo_frame.pitches[0] * this->vo_frame.height);
  27.890 +      format = VDP_YCBCR_FORMAT_YUYV;
  27.891 +    }
  27.892 +  }
  27.893 +
  27.894 +  if (data->img) {
  27.895 +    st = vdp_video_surface_getbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches);
  27.896 +    if (st != VDP_STATUS_OK)
  27.897 +      printf("vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st));
  27.898 +
  27.899 +    if (format == VDP_YCBCR_FORMAT_YV12) {
  27.900 +      yv12_to_yv12(
  27.901 +       /* Y */
  27.902 +        this->vo_frame.base[0], this->vo_frame.pitches[0],
  27.903 +        data->img, this->vo_frame.width,
  27.904 +       /* U */
  27.905 +        this->vo_frame.base[2], this->vo_frame.pitches[2],
  27.906 +        data->img+this->vo_frame.width*this->vo_frame.height, this->vo_frame.width/2,
  27.907 +       /* V */
  27.908 +        this->vo_frame.base[1], this->vo_frame.pitches[1],
  27.909 +        data->img+this->vo_frame.width*this->vo_frame.height+this->vo_frame.width*this->vo_frame.height/4, this->vo_frame.width/2,
  27.910 +       /* width x height */
  27.911 +        this->vo_frame.width, this->vo_frame.height);
  27.912 +    } else {
  27.913 +      yuy2_to_yuy2(
  27.914 +       /* src */
  27.915 +        this->vo_frame.base[0], this->vo_frame.pitches[0],
  27.916 +       /* dst */
  27.917 +        data->img, this->vo_frame.width*2,
  27.918 +       /* width x height */
  27.919 +        this->vo_frame.width, this->vo_frame.height);
  27.920 +    }
  27.921 +
  27.922 +    av_freep (&this->vo_frame.base[0]);
  27.923 +    av_freep (&this->vo_frame.base[1]);
  27.924 +    av_freep (&this->vo_frame.base[2]);
  27.925 +  }
  27.926 +}
  27.927 +
  27.928 +
  27.929 +
  27.930 +static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original)
  27.931 +{
  27.932 +  vdpau_frame_t *this = (vdpau_frame_t *)this_gen;
  27.933 +  vdpau_frame_t *orig = (vdpau_frame_t *)original;
  27.934 +  VdpStatus st;
  27.935 +  VdpYCbCrFormat format;
  27.936 +
  27.937 +  if (orig->vo_frame.format != XINE_IMGFMT_VDPAU) {
  27.938 +    fprintf(stderr, "vdpau_duplicate_frame_data: unexpected frame format 0x%08x!\n", orig->vo_frame.format);
  27.939 +    return;
  27.940 +  }
  27.941 +
  27.942 +  if(orig->vdpau_accel_data.vdp_runtime_nr != this->vdpau_accel_data.vdp_runtime_nr) {
  27.943 +    fprintf(stderr, "vdpau_duplicate_frame_data: called with invalid frame\n");
  27.944 +    return;
  27.945 +  }
  27.946 +
  27.947 +  if (!(orig->flags & VO_CHROMA_422)) {
  27.948 +    this->vo_frame.pitches[0] = 8*((orig->vo_frame.width + 7) / 8);
  27.949 +    this->vo_frame.pitches[1] = 8*((orig->vo_frame.width + 15) / 16);
  27.950 +    this->vo_frame.pitches[2] = 8*((orig->vo_frame.width + 15) / 16);
  27.951 +    this->vo_frame.base[0] = av_mallocz(this->vo_frame.pitches[0] * orig->vo_frame.height);
  27.952 +    this->vo_frame.base[1] = av_mallocz(this->vo_frame.pitches[1] * ((orig->vo_frame.height+1)/2));
  27.953 +    this->vo_frame.base[2] = av_mallocz(this->vo_frame.pitches[2] * ((orig->vo_frame.height+1)/2));
  27.954 +    format = VDP_YCBCR_FORMAT_YV12;
  27.955 +  } else {
  27.956 +    this->vo_frame.pitches[0] = 8*((orig->vo_frame.width + 3) / 4);
  27.957 +    this->vo_frame.base[0] = av_mallocz(this->vo_frame.pitches[0] * orig->vo_frame.height);
  27.958 +    format = VDP_YCBCR_FORMAT_YUYV;
  27.959 +  }
  27.960 +
  27.961 +  st = vdp_video_surface_getbits_ycbcr(orig->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches);
  27.962 +  if (st != VDP_STATUS_OK)
  27.963 +    printf("vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st));
  27.964 +
  27.965 +  st = vdp_video_surface_putbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches);
  27.966 +  if (st != VDP_STATUS_OK)
  27.967 +    printf("vo_vdpau: failed to put surface bits !! %s\n", vdp_get_error_string(st));
  27.968 +
  27.969 +  this->vdpau_accel_data.color_standard = orig->vdpau_accel_data.color_standard;
  27.970 +
  27.971 +  av_freep (&this->vo_frame.base[0]);
  27.972 +  av_freep (&this->vo_frame.base[1]);
  27.973 +  av_freep (&this->vo_frame.base[2]);
  27.974 +}
  27.975 +
  27.976 +
  27.977 +
  27.978 +static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen,
  27.979 +      uint32_t width, uint32_t height, double ratio, int format, int flags)
  27.980 +{
  27.981 +  vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
  27.982 +  vdpau_frame_t   *frame = VDPAU_FRAME(frame_gen);
  27.983 +
  27.984 +  VdpChromaType chroma = (flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420;
  27.985 +
  27.986 +  vo_frame_t orig_frame_content;
  27.987 +  if (format == XINE_IMGFMT_VDPAU) {
  27.988 +    if (frame_gen != &frame->vo_frame) {
  27.989 +      /* this is an intercepted frame, so we need to detect and propagate any
  27.990 +       * changes on the original vo_frame to all the intercepted frames */
  27.991 +       xine_fast_memcpy(&orig_frame_content, &frame->vo_frame, sizeof (vo_frame_t));
  27.992 +    }
  27.993 +  }
  27.994 +
  27.995 +  /* Check frame size and format and reallocate if necessary */
  27.996 +  if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) ||
  27.997 +        (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) {
  27.998 +
  27.999 +    /* (re-) allocate render space */
 27.1000 +    av_freep (&frame->vo_frame.base[0]);
 27.1001 +    av_freep (&frame->vo_frame.base[1]);
 27.1002 +    av_freep (&frame->vo_frame.base[2]);
 27.1003 +
 27.1004 +    if (format == XINE_IMGFMT_YV12) {
 27.1005 +      frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
 27.1006 +      frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
 27.1007 +      frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
 27.1008 +      frame->vo_frame.base[0] = av_mallocz (frame->vo_frame.pitches[0] * height);
 27.1009 +      frame->vo_frame.base[1] = av_mallocz (frame->vo_frame.pitches[1]