summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libvdpau/Makefile.am9
-rw-r--r--src/libvdpau/vdpau_mpeg12.c644
2 files changed, 652 insertions, 1 deletions
diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am
index 6cbce1016..5c372dabc 100644
--- a/src/libvdpau/Makefile.am
+++ b/src/libvdpau/Makefile.am
@@ -6,10 +6,17 @@ AM_LDFLAGS = $(xineplug_ldflags)
if HAVE_VDPAU
vdpau_h264_module = xineplug_decode_vdpau_h264.la
VDPAU_CFLAGS = -D_ISOC99_SOURCE
+
+vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la
endif
-xineplug_LTLIBRARIES = $(vdpau_h264_module)
+xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module)
xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c
xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS)
xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS)
+
+xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c
+xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS)
+xineplug_decode_vdpau_mpeg12_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS)
+
diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c
new file mode 100644
index 000000000..2f62a6f93
--- /dev/null
+++ b/src/libvdpau/vdpau_mpeg12.c
@@ -0,0 +1,644 @@
+/*
+ * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * vdpau_mpeg12.c, a mpeg1/2 video stream parser using VDPAU hardware decoder
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "xine_internal.h"
+#include "video_out.h"
+#include "buffer.h"
+#include "xineutils.h"
+#include "accel_vdpau.h"
+
+#include <vdpau/vdpau.h>
+
+
+
+#define sequence_header_code 0xb3
+#define sequence_error_code 0xb4
+#define sequence_end_code 0xb7
+#define group_start_code 0xb8
+#define extension_start_code 0xb5
+#define user_data_start_code 0xb2
+#define picture_start_code 0x00
+#define begin_slice_start_code 0x01
+#define end_slice_start_code 0xaf
+
+#define I_FRAME 1
+#define P_FRAME 2
+#define B_FRAME 3
+
+#define WANT_HEADER 1
+#define WANT_EXT 2
+#define WANT_SLICE 3
+
+
+
+/* default intra quant matrix, in zig-zag order */
+static const uint8_t default_intra_quantizer_matrix[64] = {
+ 8,
+ 16, 16,
+ 19, 16, 19,
+ 22, 22, 22, 22,
+ 22, 22, 26, 24, 26,
+ 27, 27, 27, 26, 26, 26,
+ 26, 27, 27, 27, 29, 29, 29,
+ 34, 34, 34, 29, 29, 29, 27, 27,
+ 29, 29, 32, 32, 34, 34, 37,
+ 38, 37, 35, 35, 34, 35,
+ 38, 38, 40, 40, 40,
+ 48, 48, 46, 46,
+ 56, 56, 58,
+ 69, 69,
+ 83
+};
+
+
+typedef struct {
+ VdpPictureInfoMPEG1Or2 vdp_infos;
+ int slices_count;
+ uint8_t *slices;
+ int slices_size;
+ int slices_pos;
+
+ int64_t pts;
+
+ int state;
+} picture_t;
+
+
+
+typedef struct {
+ uint32_t coded_width;
+ uint32_t coded_height;
+ uint32_t display_width;
+ uint32_t display_height;
+ uint64_t video_step; /* frame duration in pts units */
+ double ratio;
+
+ uint8_t intra_quant_matrix[64];
+ uint8_t non_intra_quant_matrix[64];
+
+ int have_header;
+
+ uint8_t *buf; /* accumulate data */
+ int bufseek;
+ uint32_t bufsize;
+ uint32_t bufpos;
+ int start;
+
+ picture_t picture;
+ vo_frame_t *forward_ref;
+
+ int64_t pts;
+} sequence_t;
+
+
+typedef struct {
+ video_decoder_class_t decoder_class;
+} vdpau_mpeg12_class_t;
+
+
+typedef struct foovideo_decoder_s {
+ video_decoder_t video_decoder; /* parent video decoder structure */
+
+ vdpau_mpeg12_class_t *class;
+ xine_stream_t *stream;
+
+ sequence_t sequence;
+
+ VdpDecoder decoder;
+
+} vdpau_mpeg12_decoder_t;
+
+
+
+static void reset_picture( picture_t *pic )
+{
+ pic->slices_count = 0;
+ pic->slices_pos = 0;
+ pic->pts = 0;
+ pic->state = WANT_HEADER;
+}
+
+
+
+static void init_picture( picture_t *pic )
+{
+ pic->slices_size = 2048;
+ pic->slices = (uint8_t*)malloc(pic->slices_size);
+ reset_picture( pic );
+}
+
+
+
+static void reset_sequence( sequence_t *sequence )
+{
+ sequence->have_header = 0;
+ sequence->bufpos = 0;
+ sequence->bufseek = 0;
+ sequence->start = -1;
+ xine_fast_memcpy( sequence->intra_quant_matrix, &default_intra_quantizer_matrix, 64 );
+ memset( sequence->non_intra_quant_matrix, 16, 64 );
+ if ( sequence->forward_ref )
+ sequence->forward_ref->free( sequence->forward_ref );
+ sequence->forward_ref = 0;
+}
+
+
+
+static uint32_t get_bits( uint8_t *b, int offbits, int nbits )
+{
+ int i, nbytes;
+ uint32_t ret = 0;
+ uint8_t *buf;
+
+ buf = b+(offbits/8);
+ offbits %=8;
+ nbytes = (offbits+nbits)/8;
+ if ( ((offbits+nbits)%8)>0 )
+ nbytes++;
+ for ( i=0; i<nbytes; i++ )
+ ret += buf[i]<<((nbytes-i-1)*8);
+ i = (4-nbytes)*8+offbits;
+ ret = ((ret<<i)>>i)>>((nbytes*8)-nbits-offbits);
+
+ return ret;
+}
+
+
+
+static void sequence_header( sequence_t *sequence, uint8_t *buf, int len )
+{
+ int i, j, off=0;
+ sequence->coded_width = get_bits( buf,0,12 );
+ sequence->coded_height = get_bits( buf,12,12 );
+ switch ( get_bits( buf+3,0,4 ) ) {
+ case 2: sequence->ratio = 4.0/3.0; break;
+ case 3: sequence->ratio = 16.0/9.0; break;
+ case 4: sequence->ratio = 2.21; break;
+ }
+ //printf( "frame_rate_code: %d\n", get_bits( buf+3,4,4 ) );
+ //printf( "bit_rate_value: %d\n", get_bits( buf+4,0,18 ) );
+ //printf( "marker_bit: %d\n", get_bits( buf+6,2,1 ) );
+ //printf( "vbv_buffer_size_value: %d\n", get_bits( buf+6,3,10 ) );
+ //printf( "constrained_parameters_flag: %d\n", get_bits( buf+7,5,1 ) );
+ i = get_bits( buf+7,6,1 );
+ if ( i ) {
+ for ( j=0; j<64; ++j ) {
+ sequence->intra_quant_matrix[j] = get_bits( buf+7+j,7,8 );
+ }
+ off = 64;
+ }
+ //printf( "load_intra_quantizer_matrix: %d\n", i );
+ i = get_bits( buf+7+off,7,1 );
+ //printf( "load_non_intra_quantizer_matrix: %d\n", i );
+ if ( i ) {
+ for ( j=0; j<64; ++j ) {
+ sequence->non_intra_quant_matrix[j] = get_bits( buf+8+off+j,0,8 );
+ }
+ }
+ sequence->have_header = 1;
+}
+
+
+
+static void picture_header( sequence_t *sequence, uint8_t *buf, int len )
+{
+ int i = get_bits( buf,10,3 );
+ printf( "!!!!!!!!!!!!!!! picture type : %d !!!!!!!!!!!!!!!!!!!!!!!!!!\n", i );
+ if ( (i!=I_FRAME && i!=P_FRAME) || sequence->picture.state!=WANT_HEADER )
+ return;
+ reset_picture( &sequence->picture );
+ sequence->picture.vdp_infos.picture_coding_type = i;
+ sequence->picture.vdp_infos.forward_reference = VDP_INVALID_HANDLE;
+ sequence->picture.vdp_infos.backward_reference = VDP_INVALID_HANDLE;
+ sequence->picture.vdp_infos.full_pel_forward_vector = 0;
+ sequence->picture.vdp_infos.full_pel_backward_vector = 0;
+ sequence->picture.state = WANT_EXT;
+ //printf( "temporal_reference: %d\n", get_bits( buf,0,10 ) );
+ //printf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) );
+}
+
+
+
+static void sequence_extension( uint8_t *buf, int len )
+{
+ printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) );
+ printf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) );
+ printf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) );
+ printf( "chroma_format: %d\n", get_bits( buf,13,2 ) );
+ printf( "horizontal_size_extension: %d\n", get_bits( buf,15,2 ) );
+ printf( "vertical_size_extension: %d\n", get_bits( buf,17,2 ) );
+ printf( "bit_rate_extension: %d\n", get_bits( buf,19,12 ) );
+ printf( "marker_bit: %d\n", get_bits( buf,31,1 ) );
+ printf( "vbv_buffer_size_extension: %d\n", get_bits( buf+4,0,8 ) );
+ printf( "low_delay: %d\n", get_bits( buf+5,0,1 ) );
+ printf( "frame_rate_extension_n: %d\n", get_bits( buf+5,1,2 ) );
+ printf( "frame_rate_extension_d: %d\n", get_bits( buf+5,3,5 ) );
+}
+
+
+
+static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int len )
+{
+ if ( sequence->picture.state!=WANT_EXT )
+ return;
+ sequence->picture.vdp_infos.f_code[0][0] = get_bits( buf,4,4 );
+ sequence->picture.vdp_infos.f_code[0][1] = get_bits( buf,8,4 );
+ sequence->picture.vdp_infos.f_code[1][0] = get_bits( buf,12,4 );
+ sequence->picture.vdp_infos.f_code[1][1] = get_bits( buf,16,4 );
+ //printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) );
+ //printf( "f_code_0_0: %d\n", get_bits( buf,4,4 ) );
+ //printf( "f_code_0_1: %d\n", get_bits( buf,8,4 ) );
+ //printf( "f_code_1_0: %d\n", get_bits( buf,12,4 ) );
+ //printf( "f_code_1_1: %d\n", get_bits( buf,16,4 ) );
+ sequence->picture.vdp_infos.intra_dc_precision = get_bits( buf,20,2 );
+ //printf( "intra_dc_precision: %d\n", get_bits( buf,20,2 ) );
+ sequence->picture.vdp_infos.picture_structure = get_bits( buf,22,2 );
+ //printf( "picture_structure: %d\n", get_bits( buf,22,2 ) );
+ sequence->picture.vdp_infos.top_field_first = get_bits( buf,24,1 );
+ //printf( "top_field_first: %d\n", get_bits( buf,24,1 ) );
+ sequence->picture.vdp_infos.frame_pred_frame_dct = get_bits( buf,25,1 );
+ //printf( "frame_pred_frame_dct: %d\n", get_bits( buf,25,1 ) );
+ sequence->picture.vdp_infos.concealment_motion_vectors = get_bits( buf,26,1 );
+ //printf( "concealment_motion_vectors: %d\n", get_bits( buf,26,1 ) );
+ sequence->picture.vdp_infos.q_scale_type = get_bits( buf,27,1 );
+ //printf( "q_scale_type: %d\n", get_bits( buf,27,1 ) );
+ sequence->picture.vdp_infos.intra_vlc_format = get_bits( buf,28,1 );
+ //printf( "intra_vlc_format: %d\n", get_bits( buf,28,1 ) );
+ sequence->picture.vdp_infos.alternate_scan = get_bits( buf,29,1 );
+ //printf( "alternate_scan: %d\n", get_bits( buf,29,1 ) );
+ //printf( "repeat_first_field: %d\n", get_bits( buf,30,1 ) );
+ //printf( "chroma_420_type: %d\n", get_bits( buf,31,1 ) );
+ //printf( "progressive_frame: %d\n", get_bits( buf,32,1 ) );
+ sequence->picture.state = WANT_SLICE;
+}
+
+
+
+static void copy_slice( sequence_t *sequence, uint8_t *buf, int len )
+{
+ int size = sequence->picture.slices_pos+len;
+ if ( sequence->picture.slices_size < size ) {
+ sequence->picture.slices_size = size+1024;
+ sequence->picture.slices = realloc( sequence->picture.slices, sequence->picture.slices_size );
+ }
+ xine_fast_memcpy( sequence->picture.slices+sequence->picture.slices_pos, buf, len );
+ sequence->picture.slices_pos += len;
+ sequence->picture.slices_count++;
+}
+
+
+
+static void quant_matrix_extension( uint8_t *buf, int len )
+{
+}
+
+
+
+static int parse_code( sequence_t *sequence, uint8_t *buf, int len )
+{
+ if ( !sequence->have_header && buf[3]!=sequence_header_code )
+ return 0;
+
+ if ( (buf[3] >= begin_slice_start_code) && (buf[3] <= end_slice_start_code) ) {
+ if ( sequence->picture.state==WANT_SLICE )
+ copy_slice( sequence, buf, len );
+ return 0;
+ //printf( " ----------- slice_start_code: %d\n", i+3 );
+ }
+ else if ( sequence->picture.state==WANT_SLICE ) {
+ /* no more slices, decode */
+ return 1;
+ }
+
+ switch ( buf[3] ) {
+ case sequence_header_code:
+ printf( " ----------- sequence_header_code\n" );
+ sequence_header( sequence, buf+4, len-4 );
+ break;
+ case extension_start_code: {
+ switch ( get_bits( buf+4,0,4 ) ) {
+ case 1:
+ printf( " ----------- sequence_extension_start_code\n" );
+ sequence_extension( buf+4, len-4 );
+ break;
+ case 3:
+ printf( " ----------- quant_matrix_extension_start_code\n" );
+ quant_matrix_extension( buf+4, len-4 );
+ break;
+ case 8:
+ printf( " ----------- picture_coding_extension_start_code\n" );
+ picture_coding_extension( sequence, buf+4, len-4 );
+ break;
+ }
+ break;
+ }
+ case user_data_start_code:
+ printf( " ----------- user_data_start_code\n" );
+ break;
+ case group_start_code:
+ printf( " ----------- group_start_code\n" );
+ break;
+ case picture_start_code:
+ printf( " ----------- picture_start_code\n" );
+ //slice_count = 0;
+ picture_header( sequence, buf+4, len-4 );
+ break;
+ case sequence_error_code:
+ printf( " ----------- sequence_error_code\n" );
+ break;
+ case sequence_end_code:
+ printf( " ----------- sequence_end_code\n" );
+ break;
+ }
+ return 0;
+}
+
+
+
+static void decode_picture( vdpau_mpeg12_decoder_t *vd )
+{
+ sequence_t *seq = (sequence_t*)&vd->sequence;
+ picture_t *pic = (picture_t*)&seq->picture;
+
+ if ( seq->forward_ref && pic->vdp_infos.picture_coding_type==P_FRAME ) {
+ vdpau_accel_t *back_accel = (vdpau_accel_t*)seq->forward_ref->accel_data;
+ pic->vdp_infos.forward_reference = back_accel->surface;
+ }
+ pic->vdp_infos.slice_count = pic->slices_count;
+ xine_fast_memcpy( &pic->vdp_infos.intra_quantizer_matrix, &seq->intra_quant_matrix, 64 );
+ xine_fast_memcpy( &pic->vdp_infos.non_intra_quantizer_matrix, &seq->non_intra_quant_matrix, 64 );
+ pic->state = WANT_HEADER;
+ vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height,
+ seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS);
+ vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data;
+ VdpStatus st;
+ if ( vd->decoder==VDP_INVALID_HANDLE ) {
+ st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, seq->coded_width, seq->coded_height, &vd->decoder);
+ if ( st!=VDP_STATUS_OK )
+ printf( "vdpau_mpeg12: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) );
+ }
+ if ( accel->surface==VDP_INVALID_HANDLE ) {
+ st = accel->vdp_video_surface_create( accel->vdp_device, VDP_CHROMA_TYPE_420, seq->coded_width, seq->coded_height, &accel->surface);
+ if ( st!=VDP_STATUS_OK )
+ printf( "vdpau_mpeg12: failed to create surface !! %s\n", accel->vdp_get_error_string( st ) );
+ }
+ VdpBitstreamBuffer vbit;
+ vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION;
+ vbit.bitstream = seq->picture.slices;
+ vbit.bitstream_bytes = seq->picture.slices_pos;
+ st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit );
+ if ( st!=VDP_STATUS_OK )
+ printf( "vdpau_mpeg12: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) );
+ else
+ printf( "vdpau_mpeg12: DECODER SUCCESS !! \n" );
+
+ //img->duration = 3600;
+ img->pts = seq->pts;
+ img->bad_frame = 0;
+ img->draw( img, vd->stream );
+
+ if ( seq->forward_ref )
+ seq->forward_ref->free( seq->forward_ref );
+ seq->forward_ref = img;
+}
+
+
+
+/*
+ * This function receives a buffer of data from the demuxer layer and
+ * figures out how to handle it based on its header flags.
+ */
+static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
+
+ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
+ sequence_t *seq = (sequence_t*)&this->sequence;
+
+ /* a video decoder does not care about this flag (?) */
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW)
+ return;
+
+ if (buf->decoder_flags & BUF_FLAG_FRAMERATE) {
+ //this->video_step = buf->decoder_info[0];
+ //_x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step);
+ }
+
+ if ( buf->pts ) {
+ seq->pts = buf->pts;
+ //printf("vdpau_mpeg12_decode_data: new pts : %lld\n", buf->pts );
+ }
+
+ int size = seq->bufpos+buf->size;
+ if ( seq->bufsize < size ) {
+ seq->bufsize = size+1024;
+ seq->buf = realloc( seq->buf, seq->bufsize );
+ printf("sequence buffer realloced = %d\n", seq->bufsize );
+ }
+ xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size );
+ seq->bufpos += buf->size;
+
+ while ( seq->bufseek < seq->bufpos-4 ) {
+ uint8_t *buf = seq->buf+seq->bufseek;
+ if ( buf[0]==0 && buf[1]==0 && buf[2]==1 ) {
+ if ( seq->start<0 ) {
+ seq->start = seq->bufseek;
+ }
+ else {
+ if ( parse_code( seq, seq->buf+seq->start, seq->bufseek-seq->start ) ) {
+ decode_picture( this );
+ //seq->pts += 3600;
+ parse_code( seq, seq->buf+seq->start, seq->bufseek-seq->start );
+ }
+ uint8_t *tmp = (uint8_t*)malloc(seq->bufsize);
+ xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek );
+ seq->bufpos -= seq->bufseek;
+ seq->start = -1;
+ seq->bufseek = -1;
+ free( seq->buf );
+ seq->buf = tmp;
+ }
+ }
+ ++seq->bufseek;
+ }
+
+}
+
+/*
+ * This function is called when xine needs to flush the system.
+ */
+static void vdpau_mpeg12_flush (video_decoder_t *this_gen) {
+}
+
+/*
+ * This function resets the video decoder.
+ */
+static void vdpau_mpeg12_reset (video_decoder_t *this_gen) {
+ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
+
+ //this->size = 0;
+}
+
+/*
+ * The decoder should forget any stored pts values here.
+ */
+static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) {
+ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
+
+}
+
+/*
+ * This function frees the video decoder instance allocated to the decoder.
+ */
+static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) {
+
+ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen;
+
+ /*if (this->buf) {
+ free (this->buf);
+ this->buf = NULL;
+ }
+
+ if (this->decoder_ok) {
+ this->decoder_ok = 0;
+ this->stream->video_out->close(this->stream->video_out, this->stream);
+ }*/
+
+ free( this->sequence.picture.slices );
+ free( this->sequence.buf );
+ free( this_gen );
+}
+
+/*
+ * This function allocates, initializes, and returns a private video
+ * decoder structure.
+ */
+static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) {
+
+ vdpau_mpeg12_decoder_t *this ;
+
+ /* the videoout must be vdpau-capable to support this decoder */
+ if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_MPEG12) )
+ return NULL;
+
+ this = (vdpau_mpeg12_decoder_t *) calloc(1, sizeof(vdpau_mpeg12_decoder_t));
+
+ this->video_decoder.decode_data = vdpau_mpeg12_decode_data;
+ this->video_decoder.flush = vdpau_mpeg12_flush;
+ this->video_decoder.reset = vdpau_mpeg12_reset;
+ this->video_decoder.discontinuity = vdpau_mpeg12_discontinuity;
+ this->video_decoder.dispose = vdpau_mpeg12_dispose;
+
+ this->stream = stream;
+ this->class = (vdpau_mpeg12_class_t *) class_gen;
+
+ this->sequence.bufsize = 1024;
+ this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize);
+ this->sequence.forward_ref = 0;
+ reset_sequence( &this->sequence );
+
+ init_picture( &this->sequence.picture );
+
+ this->decoder = VDP_INVALID_HANDLE;
+
+ return &this->video_decoder;
+}
+
+/*
+ * This function returns a brief string that describes (usually with the
+ * decoder's most basic name) the video decoder plugin.
+ */
+static char *get_identifier (video_decoder_class_t *this) {
+ return "vdpau_mpeg12";
+}
+
+/*
+ * This function returns a slightly longer string describing the video
+ * decoder plugin.
+ */
+static char *get_description (video_decoder_class_t *this) {
+ return "vdpau_mpeg12: mpeg1/2 decoder plugin using VDPAU hardware decoding.\n"
+ "Must be used along with video_out_vdpau.";
+}
+
+/*
+ * This function frees the video decoder class and any other memory that was
+ * allocated.
+ */
+static void dispose_class (video_decoder_class_t *this) {
+ free (this);
+}
+
+/*
+ * This function allocates a private video decoder class and initializes
+ * the class's member functions.
+ */
+static void *init_plugin (xine_t *xine, void *data) {
+
+ vdpau_mpeg12_class_t *this;
+
+ this = (vdpau_mpeg12_class_t *) calloc(1, sizeof(vdpau_mpeg12_class_t));
+
+ this->decoder_class.open_plugin = open_plugin;
+ this->decoder_class.get_identifier = get_identifier;
+ this->decoder_class.get_description = get_description;
+ this->decoder_class.dispose = dispose_class;
+
+ return this;
+}
+
+/*
+ * This is a list of all of the internal xine video buffer types that
+ * this decoder is able to handle. Check src/xine-engine/buffer.h for a
+ * list of valid buffer types (and add a new one if the one you need does
+ * not exist). Terminate the list with a 0.
+ */
+static const uint32_t video_types[] = {
+ BUF_VIDEO_MPEG,
+ 0
+};
+
+/*
+ * This data structure combines the list of supported xine buffer types and
+ * the priority that the plugin should be given with respect to other
+ * plugins that handle the same buffer type. A plugin with priority (n+1)
+ * will be used instead of a plugin with priority (n).
+ */
+static const decoder_info_t dec_info_video = {
+ video_types, /* supported types */
+ 8 /* priority */
+};
+
+/*
+ * The plugin catalog entry. This is the only information that this plugin
+ * will export to the public.
+ */
+const plugin_info_t xine_plugin_info[] EXPORTED = {
+ /* { type, API, "name", version, special_info, init_function } */
+ { PLUGIN_VIDEO_DECODER, 18, "vdpau_mpeg12", XINE_VERSION_CODE, &dec_info_video, init_plugin },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};