diff options
Diffstat (limited to 'src/video_out/xvmc_vld.c')
-rw-r--r-- | src/video_out/xvmc_vld.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/video_out/xvmc_vld.c b/src/video_out/xvmc_vld.c new file mode 100644 index 000000000..d542ca515 --- /dev/null +++ b/src/video_out/xvmc_vld.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2004 the Unichrome project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xvmc_vld.c,v 1.1 2004/09/28 18:49:40 miguelfreitas Exp $ + * + * xvmc_vld.c, X11 decoding accelerated video extension interface for xine + * + * Author: Thomas Hellström, (2004) + */ + +#include "xxmc.h" +#include <unistd.h> + +#ifdef HAVE_VLDXVMC +void xvmc_vld_frame(struct vo_frame_s *this_gen) + +{ + vo_frame_t *this = (vo_frame_t *) this_gen; + xxmc_frame_t + *cf = (xxmc_frame_t *) this; + xine_vld_frame_t + *vft = &(cf->xxmc_data.vld_frame); + xxmc_frame_t + *ff = (xxmc_frame_t *) vft->forward_reference_frame, + *bf = (xxmc_frame_t *) vft->backward_reference_frame; + XvMCMpegControl ctl; + xxmc_driver_t + *driver = (xxmc_driver_t *) cf->vo_frame.driver; + XvMCSurface *fs=0, *bs=0; + XvMCQMatrix qmx; + + ctl.BHMV_range = vft->mv_ranges[0][0]; + ctl.BVMV_range = vft->mv_ranges[0][1]; + ctl.FHMV_range = vft->mv_ranges[1][0]; + ctl.FVMV_range = vft->mv_ranges[1][1]; + ctl.picture_structure = vft->picture_structure; + ctl.intra_dc_precision = vft->intra_dc_precision; + ctl.picture_coding_type = vft->picture_coding_type; + ctl.mpeg_coding = (vft->mpeg_coding == 0) ? XVMC_MPEG_1 : XVMC_MPEG_2; + ctl.flags = 0; + ctl.flags |= (vft->progressive_sequence) ? + XVMC_PROGRESSIVE_SEQUENCE : 0 ; + ctl.flags |= (vft->scan) ? + XVMC_ALTERNATE_SCAN : XVMC_ZIG_ZAG_SCAN; + ctl.flags |= (vft->pred_dct_frame) ? + XVMC_PRED_DCT_FRAME : XVMC_PRED_DCT_FIELD; + ctl.flags |= (this->top_field_first) ? + XVMC_TOP_FIELD_FIRST : XVMC_BOTTOM_FIELD_FIRST; + ctl.flags |= (vft->concealment_motion_vectors) ? + XVMC_CONCEALMENT_MOTION_VECTORS : 0 ; + ctl.flags |= (vft->q_scale_type) ? + XVMC_Q_SCALE_TYPE : 0; + ctl.flags |= (vft->intra_vlc_format) ? + XVMC_INTRA_VLC_FORMAT : 0; + ctl.flags |= (vft->second_field) ? + XVMC_SECOND_FIELD : 0 ; + + if (ff) fs=ff->xvmc_surf; + if (bf) bs=bf->xvmc_surf; + + /* + * Below is for interlaced streams and second_field. + */ + + if (ctl.picture_coding_type == XVMC_P_PICTURE) + bs = cf->xvmc_surf; + + if ((qmx.load_intra_quantiser_matrix = vft->load_intra_quantizer_matrix)) { + memcpy(qmx.intra_quantiser_matrix,vft->intra_quantizer_matrix, + sizeof(qmx.intra_quantiser_matrix)); + } + if ((qmx.load_non_intra_quantiser_matrix = vft->load_non_intra_quantizer_matrix)) { + memcpy(qmx.non_intra_quantiser_matrix,vft->non_intra_quantizer_matrix, + sizeof(qmx.non_intra_quantiser_matrix)); + } + qmx.load_chroma_intra_quantiser_matrix = 0; + qmx.load_chroma_non_intra_quantiser_matrix = 0; + xvmc_context_reader_lock( &driver->xvmc_lock ); + if ( ! xxmc_xvmc_surface_valid( driver, cf->xvmc_surf)) { + cf->xxmc_data.result = 128; + xvmc_context_reader_unlock( &driver->xvmc_lock ); + return; + } + XVMCLOCKDISPLAY( driver->display ); + XvMCLoadQMatrix(driver->display, &driver->context, &qmx); + while((cf->xxmc_data.result = + XvMCBeginSurface(driver->display, &driver->context, cf->xvmc_surf, + fs, bs, &ctl))); + XVMCUNLOCKDISPLAY( driver->display ); + xvmc_context_reader_unlock( &driver->xvmc_lock ); + driver->cpu_saver = 0.; +} + +void xvmc_vld_slice(vo_frame_t *this_gen) +{ + xxmc_frame_t + *cf = (xxmc_frame_t *) this_gen; + xxmc_driver_t + *driver = (xxmc_driver_t *) cf->vo_frame.driver; + + xvmc_context_reader_lock( &driver->xvmc_lock ); + if ( ! xxmc_xvmc_surface_valid( driver, cf->xvmc_surf)) { + cf->xxmc_data.result = 128; + xvmc_context_reader_unlock( &driver->xvmc_lock ); + return; + } + XVMCLOCKDISPLAY( driver->display ); + cf->xxmc_data.result = + XvMCPutSlice2(driver->display,&driver->context,cf->xxmc_data.slice_data, + cf->xxmc_data.slice_data_size,cf->xxmc_data.slice_code); + /* + * If CPU-saving mode is enabled, sleep after every xxmc->sleep slice. This will free + * up the cpu while the decoder is working on the slice. The value of xxmc->sleep is calculated + * so that the decoder thread sleeps at most 50% of the frame delay, + * assuming a 2.6 kernel clock of 1000 Hz. + */ + + XVMCUNLOCKDISPLAY( driver->display ); + xvmc_context_reader_unlock( &driver->xvmc_lock ); + if (driver->cpu_save_enabled) { + driver->cpu_saver += 1.; + if (driver->cpu_saver >= cf->xxmc_data.sleep) { + usleep(1); + driver->cpu_saver -= cf->xxmc_data.sleep; + } + } +} +#endif + +extern void xvmc_vld_flush(vo_frame_t *this_gen) +{ + + xxmc_frame_t + *frame = (xxmc_frame_t *) this_gen; + xxmc_driver_t + *driver = (xxmc_driver_t *) this_gen->driver; + + xvmc_context_reader_lock( &driver->xvmc_lock ); + + if ( ! xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) { + frame->xxmc_data.result = 128; + xvmc_context_reader_unlock( &driver->xvmc_lock ); + return; + } + + XVMCLOCKDISPLAY( driver->display ); + frame->xxmc_data.result = XvMCFlushSurface( driver->display, frame->xvmc_surf ); + frame->xxmc_data.result = XvMCSyncSurface( driver->display, frame->xvmc_surf ); + XVMCUNLOCKDISPLAY( driver->display ); + + xvmc_context_reader_unlock( &driver->xvmc_lock ); + +} + |