/* * Copyright (C) 2000-2004 the xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * XvMC image support by Jack Kelliher */ #include "xxmc.h" static void calc_DMV(int DMV[][2], int *dmvector, int mvx, int mvy, int picture_structure, int top_field_first) { if (picture_structure==VO_BOTH_FIELDS) { if (top_field_first) { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy +(mvy>0))>>1) + dmvector[1] - 1; /* vector for prediction of bottom field from top field */ DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1; } else { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1; /* vector for prediction of bottom field from top field */ DMV[1][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((mvy +(mvy>0))>>1) + dmvector[1] + 1; } } else { /* vector for prediction from field of opposite 'parity' */ DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1]; /* correct for vertical field shift */ if (picture_structure==VO_TOP_FIELD) DMV[0][1]--; else DMV[0][1]++; } } static void xvmc_render_macro_blocks(vo_frame_t *current_image, vo_frame_t *backward_ref_image, vo_frame_t *forward_ref_image, int picture_structure, int second_field, xvmc_macroblocks_t *macroblocks) { xxmc_driver_t *this = (xxmc_driver_t *) current_image->driver; xxmc_frame_t *current_frame = (xxmc_frame_t *) current_image; xxmc_frame_t *forward_frame = (xxmc_frame_t *) forward_ref_image; xxmc_frame_t *backward_frame = (xxmc_frame_t *) backward_ref_image; int flags; lprintf ("xvmc_render_macro_blocks\n"); lprintf ("slices %d 0x%08lx 0x%08lx 0x%08lx\n", macroblocks->slices, (long) current_frame, (long) backward_frame, (long) forward_frame); flags = second_field; XVMCLOCKDISPLAY( this->display); XvMCRenderSurface(this->display, &this->context, picture_structure, current_frame->xvmc_surf, forward_frame ? forward_frame->xvmc_surf : NULL, backward_frame ? backward_frame->xvmc_surf : NULL, flags, macroblocks->slices, 0, ¯oblocks->macro_blocks, ¯oblocks->blocks); XVMCUNLOCKDISPLAY( this->display); } void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, int (*mv_field_sel)[2], int *dmvector, int cbp, int dct_type, vo_frame_t *current_frame, vo_frame_t *forward_ref_frame, vo_frame_t *backward_ref_frame, int picture_structure, int second_field, int (*f_mot_pmv)[2], int (*b_mot_pmv)[2]) { xxmc_driver_t *this = (xxmc_driver_t *) current_frame->driver; xvmc_macroblocks_t *mbs = &this->macroblocks; int top_field_first = current_frame->top_field_first; int picture_coding_type = current_frame->picture_coding_type; mbs->macroblockptr->x = x; mbs->macroblockptr->y = y; if(mb_type & XINE_MACROBLOCK_INTRA) { mbs->macroblockptr->macroblock_type = XVMC_MB_TYPE_INTRA; } else { mbs->macroblockptr->macroblock_type = 0; /* XvMC doesn't support skips */ if(!(mb_type & (XINE_MACROBLOCK_MOTION_BACKWARD | XINE_MACROBLOCK_MOTION_FORWARD))) { mb_type |= XINE_MACROBLOCK_MOTION_FORWARD; motion_type = (picture_structure == VO_BOTH_FIELDS) ? XINE_MC_FRAME : XINE_MC_FIELD; mbs->macroblockptr->PMV[0][0][0] = 0; mbs->macroblockptr->PMV[0][0][1] = 0; } else { if(mb_type & XINE_MACROBLOCK_MOTION_BACKWARD) { mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD; mbs->macroblockptr->PMV[0][1][0] = b_mot_pmv[0][0]; mbs->macroblockptr->PMV[0][1][1] = b_mot_pmv[0][1]; mbs->macroblockptr->PMV[1][1][0] = b_mot_pmv[1][0]; mbs->macroblockptr->PMV[1][1][1] = b_mot_pmv[1][1]; } if(mb_type & XINE_MACROBLOCK_MOTION_FORWARD) { mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD; mbs->macroblockptr->PMV[0][0][0] = f_mot_pmv[0][0]; mbs->macroblockptr->PMV[0][0][1] = f_mot_pmv[0][1]; mbs->macroblockptr->PMV[1][0][0] = f_mot_pmv[1][0]; mbs->macroblockptr->PMV[1][0][1] = f_mot_pmv[1][1]; } } if((mb_type & XINE_MACROBLOCK_PATTERN) && cbp) mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_PATTERN; mbs->macroblockptr->motion_type = motion_type; if(motion_type == XINE_MC_DMV) { int DMV[2][2]; if(picture_structure == VO_BOTH_FIELDS) { calc_DMV(DMV,dmvector, f_mot_pmv[0][0], f_mot_pmv[0][1]>>1, picture_structure, top_field_first); mbs->macroblockptr->PMV[1][0][0] = DMV[0][0]; mbs->macroblockptr->PMV[1][0][1] = DMV[0][1]; mbs->macroblockptr->PMV[1][1][0] = DMV[1][0]; mbs->macroblockptr->PMV[1][1][1] = DMV[1][1]; } else { calc_DMV(DMV,dmvector, f_mot_pmv[0][0], f_mot_pmv[0][1]>>1, picture_structure, top_field_first); mbs->macroblockptr->PMV[0][1][0] = DMV[0][0]; mbs->macroblockptr->PMV[0][1][1] = DMV[0][1]; } } if((motion_type == XINE_MC_FIELD) || (motion_type == XINE_MC_16X8)) { mbs->macroblockptr->motion_vertical_field_select = 0; if(mv_field_sel[0][0]) mbs->macroblockptr->motion_vertical_field_select |= 1; if(mv_field_sel[0][1]) mbs->macroblockptr->motion_vertical_field_select |= 2; if(mv_field_sel[1][0]) mbs->macroblockptr->motion_vertical_field_select |= 4; if(mv_field_sel[1][1]) mbs->macroblockptr->motion_vertical_field_select |= 8; } } /* else of if(mb_type & XINE_MACROBLOCK_INTRA) */ mbs->macroblockptr->index = ((unsigned long)mbs->xine_mc.blockptr - (unsigned long)mbs->xine_mc.blockbaseptr) >> 7; mbs->macroblockptr->dct_type = dct_type; mbs->macroblockptr->coded_block_pattern = cbp; cbp &= 0x3F; mbs->macroblockptr->coded_block_pattern = cbp; while(cbp) { if(cbp & 1) mbs->macroblockptr->index--; cbp >>= 1; } #ifdef PRINTDATA printf("\n"); printf("-- %04d %04d %02x %02x %02x %02x",mbs->macroblockptr->x,mbs->macroblockptr->y,mbs->macroblockptr->macroblock_type, mbs->macroblockptr->motion_type,mbs->macroblockptr->motion_vertical_field_select,mbs->macroblockptr->dct_type); printf(" [%04d %04d %04d %04d %04d %04d %04d %04d] ", mbs->macroblockptr->PMV[0][0][0],mbs->macroblockptr->PMV[0][0][1],mbs->macroblockptr->PMV[0][1][0],mbs->macroblockptr->PMV[0][1][1], mbs->macroblockptr->PMV[1][0][0],mbs->macroblockptr->PMV[1][0][1],mbs->macroblockptr->PMV[1][1][0],mbs->macroblockptr->PMV[1][1][1]); printf(" %04d %04x\n",mbs->macroblockptr->index,mbs->macroblockptr->coded_block_pattern); #endif mbs->num_blocks++; mbs->macroblockptr++; if(mbs->num_blocks == mbs->slices) { #ifdef PRINTDATA printf("macroblockptr %lx", mbs->macroblockptr); printf("** RenderSurface %04d %04x\n",picture_structure, second_field ? XVMC_SECOND_FIELD : 0); fflush(stdout); #endif #ifdef PRINTFRAME printf(" target %08x past %08x future %08x\n", current_frame, forward_ref_frame, backward_ref_frame); #endif #ifdef PRINTFRAME if (picture_coding_type == XINE_PICT_P_TYPE) printf(" coding type P_TYPE\n"); if (picture_coding_type == XINE_PICT_I_TYPE) printf(" coding type I_TYPE\n"); if (picture_coding_type == XINE_PICT_B_TYPE) printf(" coding type B_TYPE\n"); if (picture_coding_type == XINE_PICT_D_TYPE) printf(" coding type D_TYPE\n"); fflush(stdout); #endif xvmc_render_macro_blocks( current_frame, (picture_coding_type == XINE_PICT_B_TYPE) ? backward_ref_frame : NULL, (picture_coding_type != XINE_PICT_I_TYPE) ? forward_ref_frame : NULL, picture_structure, second_field ? XVMC_SECOND_FIELD : 0, mbs); mbs->num_blocks = 0; mbs->macroblockptr = mbs->macroblockbaseptr; mbs->xine_mc.blockptr = mbs->xine_mc.blockbaseptr; } }