diff options
-rw-r--r-- | src/libvdpau/Makefile.am | 7 | ||||
-rw-r--r-- | src/libvdpau/vdpau_vc1.c | 618 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 1 |
3 files changed, 625 insertions, 1 deletions
diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am index dc7ace0a7..140168483 100644 --- a/src/libvdpau/Makefile.am +++ b/src/libvdpau/Makefile.am @@ -8,9 +8,11 @@ vdpau_h264_module = xineplug_decode_vdpau_h264.la VDPAU_CFLAGS = -D_ISOC99_SOURCE vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la + +vdpau_vc1_module = xineplug_decode_vdpau_vc1.la endif -xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) +xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) $(vdpau_vc1_module) xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) @@ -20,3 +22,6 @@ xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS) xineplug_decode_vdpau_mpeg12_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) +xineplug_decode_vdpau_vc1_la_SOURCES = vdpau_vc1.c +xineplug_decode_vdpau_vc1_la_CFLAGS = $(AM_CFLAGS) +xineplug_decode_vdpau_vc1_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c new file mode 100644 index 000000000..74b70d8ff --- /dev/null +++ b/src/libvdpau/vdpau_vc1.c @@ -0,0 +1,618 @@ +/* + * 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_vc1.c, a vc1 video stream parser using VDPAU hardware decoder + * + */ + +#define LOG +#define LOG_MODULE "vdpau_vc1" + + +#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 0x0f +#define sequence_end_code 0x0a +#define entry_point_code 0x0e +#define frame_start_code 0x0d +#define field_start_code 0x0c +#define slice_start_code 0x0b + +#define PICTURE_FRAME 0 +#define PICTURE_FRAME_INTERLACE 2 +#define PICTURE_FIELD_INTERLACE 3 + +#define WANT_HEADER 1 +#define WANT_EXT 2 +#define WANT_SLICE 3 + + + +typedef struct { + VdpPictureInfoVC1 vdp_infos; + + int progressive_frame; + int state; +} picture_t; + + + +typedef struct { + uint32_t coded_width; + uint32_t coded_height; + + uint64_t video_step; /* frame duration in pts units */ + double ratio; + VdpDecoderProfile profile; + + int have_header; + + uint8_t *buf; /* accumulate data */ + uint32_t bufsize; + uint32_t bufpos; + + picture_t picture; + vo_frame_t *forward_ref; + vo_frame_t *backward_ref; + + int64_t seq_pts; + int64_t cur_pts; + + vdpau_accel_t *accel_vdpau; + + int vdp_runtime_nr; + +} sequence_t; + + + +typedef struct { + video_decoder_class_t decoder_class; +} vdpau_vc1_class_t; + + + +typedef struct vdpau_vc1_decoder_s { + video_decoder_t video_decoder; /* parent video decoder structure */ + + vdpau_vc1_class_t *class; + xine_stream_t *stream; + + sequence_t sequence; + + VdpDecoder decoder; + VdpDecoderProfile decoder_profile; + uint32_t decoder_width; + uint32_t decoder_height; + +} vdpau_vc1_decoder_t; + + + +static void reset_picture( picture_t *pic ) +{ + lprintf( "reset_picture\n" ); + /*pic->vdp_infos.picture_structure = 0; + pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0; + pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1; + pic->vdp_infos2.concealment_motion_vectors = pic->vdp_infos.concealment_motion_vectors = 0; + pic->vdp_infos2.intra_vlc_format = pic->vdp_infos.intra_vlc_format = 0; + pic->vdp_infos2.alternate_scan = pic->vdp_infos.alternate_scan = 0; + pic->vdp_infos2.q_scale_type = pic->vdp_infos.q_scale_type = 0; + pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 0; + pic->slices_count = 0; + pic->slices_count2 = 0; + pic->slices_pos = 0; + pic->slices_pos_top = 0; + pic->state = WANT_HEADER;*/ +} + + + +static void init_picture( picture_t *pic ) +{ + reset_picture( pic ); +} + + + +static void init_sequence( sequence_t *sequence ) +{ + lprintf( "init_sequence\n" ); + sequence->have_header = 0; + sequence->bufpos = 0; + sequence->seq_pts = sequence->cur_pts = 0; + sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; + sequence->ratio = 0; + sequence->video_step = 0; + if ( sequence->forward_ref ) + sequence->forward_ref->free( sequence->forward_ref ); + sequence->forward_ref = NULL; + if ( sequence->backward_ref ) + sequence->backward_ref->free( sequence->backward_ref ); + sequence->backward_ref = NULL; +} + + + +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_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ +} + + + +static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + + if ( len < 4 ) + return; + + lprintf( "sequence_header\n" ); + + switch ( get_bits(buf,0,2) ) { + case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; break; + case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; break; + case 3: return sequence_header_advanced( this_gen, buf, len ); break; + default: return; /* illegal value, broken header? */ + } + + sequence->picture.vdp_infos.loopfilter = get_bits(buf,12,1); + sequence->picture.vdp_infos.multires = get_bits(buf,14,1); + sequence->picture.vdp_infos.fastuvmc = get_bits(buf,16,1); + sequence->picture.vdp_infos.extended_mv = get_bits(buf,17,1); + sequence->picture.vdp_infos.dquant = get_bits(buf,18,2); + sequence->picture.vdp_infos.vstransform = get_bits(buf,20,1); + sequence->picture.vdp_infos.overlap = get_bits(buf,22,1); + sequence->picture.vdp_infos.syncmarker = get_bits(buf,23,1); + sequence->picture.vdp_infos.rangered = get_bits(buf,24,1); + sequence->picture.vdp_infos.maxbframes = get_bits(buf,25,3); + sequence->picture.vdp_infos.quantizer = get_bits(buf,28,2); + sequence->picture.vdp_infos.finterpflag = get_bits(buf,30,1); + + if ( !sequence->have_header ) { + sequence->have_header = 1; + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); + _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" ); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this_gen->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = sequence->coded_width; + data.height = sequence->coded_height; + data.aspect = sequence->ratio; + xine_event_send( this_gen->stream, &event ); + } +} + + + +static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); + + int off=2; + + if ( info->finterpflag ) + ++off; + if ( info->rangered ) + ++off; + if ( !info->maxbframes ) + info->picture_type = get_bits( buf,off,1 ); + else { + int ptype = get_bits( buf,off,1 ); + if ( ptype ) { + info->picture_type = ptype; + ++off; + } + else { + info->picture_type = get_bits( buf,off,2 ); + off += 2; + } + } + +} + + + +static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) +{ + sequence_t *seq = (sequence_t*)&vd->sequence; + picture_t *pic = (picture_t*)&seq->picture; + + VdpStatus st; + if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) { + if ( vd->decoder!=VDP_INVALID_HANDLE ) { + accel->vdp_decoder_destroy( vd->decoder ); + vd->decoder = VDP_INVALID_HANDLE; + } + st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); + if ( st!=VDP_STATUS_OK ) + lprintf( "failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); + else { + lprintf( "decoder created.\n" ); + vd->decoder_profile = seq->profile; + vd->decoder_width = seq->coded_width; + vd->decoder_height = seq->coded_height; + seq->vdp_runtime_nr = accel->vdp_runtime_nr; + } + } + + VdpBitstreamBuffer vbit; + vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit.bitstream = seq->buf; + vbit.bitstream_bytes = seq->bufpos; + st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); + if ( st!=VDP_STATUS_OK ) + lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + else { + lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + } +} + + + +static void decode_picture( vdpau_vc1_decoder_t *vd ) +{ + sequence_t *seq = (sequence_t*)&vd->sequence; + + seq->picture.vdp_infos.picture_type = 1; + VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); + info->forward_reference = VDP_INVALID_HANDLE; + info->backward_reference = VDP_INVALID_HANDLE; + printf("%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\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + + vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, + seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + if ( !seq->accel_vdpau ) + seq->accel_vdpau = accel; + + if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) { + seq->accel_vdpau = accel; + if ( seq->forward_ref ) + seq->forward_ref->free( seq->forward_ref ); + seq->forward_ref = NULL; + if ( seq->backward_ref ) + seq->backward_ref->free( seq->backward_ref ); + seq->backward_ref = NULL; + vd->decoder = VDP_INVALID_HANDLE; + } + + decode_render( vd, accel ); + + img->pts = seq->seq_pts; + img->draw( img, vd->stream ); + img->free( img ); +} + + + +/* + * This function receives a buffer of data from the demuxer layer and + * figures out how to handle it based on its header flags. + */ +static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf) +{ + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + sequence_t *seq = (sequence_t*)&this->sequence; + + /* a video decoder does not care about this flag (?) */ + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { + lprintf("BUF_FLAG_PREVIEW\n"); + return; + } + + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { + lprintf("BUF_FLAG_FRAMERATE=%d\n", buf->decoder_info[0]); + if ( buf->decoder_info[0] > 0 ) { + this->sequence.video_step = buf->decoder_info[0]; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->sequence.video_step); + } + } + + if (buf->decoder_flags & BUF_FLAG_HEADER) { + lprintf("BUF_FLAG_HEADER\n"); + } + + if (buf->decoder_flags & BUF_FLAG_ASPECT) { + lprintf("BUF_FLAG_ASPECT\n"); + seq->ratio = (double)buf->decoder_info[1]/(double)buf->decoder_info[2]; + lprintf("arx=%d ary=%d ratio=%f\n", buf->decoder_info[1], buf->decoder_info[2], seq->ratio); + } + + if (buf->decoder_flags & BUF_FLAG_FRAME_START) { + lprintf("BUF_FLAG_FRAME_START\n"); + seq->seq_pts = buf->pts; + } + + if ( !buf->size ) + return; + + //printf("vdpau_vc1_decode_data: new pts : %lld\n", buf->pts ); + seq->cur_pts = buf->pts; + + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { + lprintf("BUF_FLAG_STDHEADER\n"); + xine_bmiheader *bih = (xine_bmiheader *) buf->content; + int bs = sizeof( xine_bmiheader ); + seq->coded_width = bih->biWidth; + seq->coded_height = bih->biHeight; + lprintf( "width=%d height=%d\n", bih->biWidth, bih->biHeight ); + if ( buf->size > bs ) { + sequence_header( this, buf->content+bs, buf->size-bs ); + } + int i; + for ( i=0; i<buf->size; ++i ) + printf("%02X ", buf->content[i] ); + printf("\n\n"); + return; + } + + int size = seq->bufpos+buf->size; + if ( seq->bufsize < size ) { + seq->bufsize = size+10000; + seq->buf = realloc( seq->buf, seq->bufsize ); + lprintf("sequence buffer realloced = %d\n", seq->bufsize ); + } + xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); + seq->bufpos += buf->size; + + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + lprintf("BUF_FLAG_FRAME_END\n"); + seq->picture.vdp_infos.slice_count = 1; + decode_picture( this ); + seq->bufpos = 0; + } + + + /*int i; + for ( i=0; i<buf->size; ++i ) + printf("%02X ", buf->content[i] ); + printf("\n\n"); + + uint8_t *buffer = buf->content; + for ( i=0; i<buf->size-4; ++i ) { + if ( buffer[i]==0 && buffer[i+1]==0 && buffer[i+2]==1 ) + printf("start code\n"); + }*/ +} + + +/* + * This function is called when xine needs to flush the system. + */ +static void vdpau_vc1_flush (video_decoder_t *this_gen) { + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_flush\n" ); +} + +/* + * This function resets the video decoder. + */ +static void vdpau_vc1_reset (video_decoder_t *this_gen) { + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_reset\n" ); + init_sequence( &this->sequence ); + + //this->size = 0; +} + +/* + * The decoder should forget any stored pts values here. + */ +static void vdpau_vc1_discontinuity (video_decoder_t *this_gen) { + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_discontinuity\n" ); + init_sequence( &this->sequence ); + +} + +/* + * This function frees the video decoder instance allocated to the decoder. + */ +static void vdpau_vc1_dispose (video_decoder_t *this_gen) { + + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_dispose\n" ); + + if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) { + this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder ); + this->decoder = VDP_INVALID_HANDLE; + } + + this->stream->video_out->close( this->stream->video_out, this->stream ); + + free( this->sequence.buf ); + free( this_gen ); +} + +/* + * This function allocates, initializes, and returns a private video + * decoder structure. + */ +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { + + vdpau_vc1_decoder_t *this ; + + lprintf( "open_plugin\n" ); + + /* the videoout must be vdpau-capable to support this decoder */ + if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_VC1) ) + return NULL; + + /* now check if vdpau has free decoder resource */ + vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + img->free(img); + VdpDecoder decoder; + VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, 1920, 1080, 2, &decoder ); + if ( st!=VDP_STATUS_OK ) { + lprintf( "can't create vdpau decoder.\n" ); + return NULL; + } + + accel->vdp_decoder_destroy( decoder ); + + this = (vdpau_vc1_decoder_t *) calloc(1, sizeof(vdpau_vc1_decoder_t)); + + this->video_decoder.decode_data = vdpau_vc1_decode_data; + this->video_decoder.flush = vdpau_vc1_flush; + this->video_decoder.reset = vdpau_vc1_reset; + this->video_decoder.discontinuity = vdpau_vc1_discontinuity; + this->video_decoder.dispose = vdpau_vc1_dispose; + + this->stream = stream; + this->class = (vdpau_vc1_class_t *) class_gen; + + this->sequence.bufsize = 10000; + this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); + this->sequence.forward_ref = 0; + this->sequence.backward_ref = 0; + this->sequence.vdp_runtime_nr = 1; + init_sequence( &this->sequence ); + + init_picture( &this->sequence.picture ); + + this->decoder = VDP_INVALID_HANDLE; + this->sequence.accel_vdpau = NULL; + + (stream->video_out->open)(stream->video_out, stream); + + return &this->video_decoder; +} + +/* + * This function returns a brief string that describes (usually with the + * decoder's most basic name) the video decoder plugin. + */ +static char *get_identifier (video_decoder_class_t *this) { + return "vdpau_vc1"; +} + +/* + * This function returns a slightly longer string describing the video + * decoder plugin. + */ +static char *get_description (video_decoder_class_t *this) { + return "vdpau_vc1: vc1 decoder plugin using VDPAU hardware decoding.\n" + "Must be used along with video_out_vdpau."; +} + +/* + * This function frees the video decoder class and any other memory that was + * allocated. + */ +static void dispose_class (video_decoder_class_t *this) { + free (this); +} + +/* + * This function allocates a private video decoder class and initializes + * the class's member functions. + */ +static void *init_plugin (xine_t *xine, void *data) { + + vdpau_vc1_class_t *this; + + this = (vdpau_vc1_class_t *) calloc(1, sizeof(vdpau_vc1_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} + +/* + * This is a list of all of the internal xine video buffer types that + * this decoder is able to handle. Check src/xine-engine/buffer.h for a + * list of valid buffer types (and add a new one if the one you need does + * not exist). Terminate the list with a 0. + */ +static const uint32_t video_types[] = { + BUF_VIDEO_VC1, BUF_VIDEO_WMV9, + 0 +}; + +/* + * This data structure combines the list of supported xine buffer types and + * the priority that the plugin should be given with respect to other + * plugins that handle the same buffer type. A plugin with priority (n+1) + * will be used instead of a plugin with priority (n). + */ +static const decoder_info_t dec_info_video = { + video_types, /* supported types */ + 8 /* priority */ +}; + +/* + * The plugin catalog entry. This is the only information that this plugin + * will export to the public. + */ +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* { type, API, "name", version, special_info, init_function } */ + { PLUGIN_VIDEO_DECODER, 18, "vdpau_vc1", XINE_VERSION_CODE, &dec_info_video, init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 845ab0079..bbf0dcc35 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -296,6 +296,7 @@ struct xine_video_port_s { #define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ #define VO_CAP_VDPAU_H264 0x00000080 /* driver can use VDPAU for H264 */ #define VO_CAP_VDPAU_MPEG12 0x00000100 /* driver can use VDPAU for mpeg1/2 */ +#define VO_CAP_VDPAU_VC1 0x00000200 /* driver can use VDPAU for mpeg1/2 */ #define VO_CAP_CUSTOM_EXTENT_OVERLAY 0x01000000 /* driver can blend custom extent overlay to output extent */ #define VO_CAP_ARGB_LAYER_OVERLAY 0x02000000 /* driver supports true color overlay */ |