Merge from 1.1; merge vdpau (with adjustments for 1.2).
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] * ((height+1)/2));
27.1010 + frame->vo_frame.base[2] = av_mallocz (frame->vo_frame.pitches[2] * ((height+1)/2)