1 /*
2  * Copyright (C) 2000-2020 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * XvMC image support by Jack Kelliher
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include "xxmc.h"
28 
29 
calc_DMV(int DMV[][2],int * dmvector,int mvx,int mvy,int picture_structure,int top_field_first)30 static void calc_DMV(int DMV[][2], int *dmvector,
31 		     int mvx, int mvy, int picture_structure, int top_field_first) {
32 
33   if (picture_structure==VO_BOTH_FIELDS) {
34     if (top_field_first) {
35       /* vector for prediction of top field from bottom field */
36       DMV[0][0] = ((mvx  +(mvx>0))>>1) + dmvector[0];
37       DMV[0][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] - 1;
38 
39       /* vector for prediction of bottom field from top field */
40       DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
41       DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1;
42     }
43     else {
44       /* vector for prediction of top field from bottom field */
45       DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
46       DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1;
47 
48       /* vector for prediction of bottom field from top field */
49       DMV[1][0] = ((mvx  +(mvx>0))>>1) + dmvector[0];
50       DMV[1][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] + 1;
51     }
52   }
53   else {
54     /* vector for prediction from field of opposite 'parity' */
55     DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0];
56     DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1];
57 
58     /* correct for vertical field shift */
59     if (picture_structure==VO_TOP_FIELD)
60       DMV[0][1]--;
61     else
62       DMV[0][1]++;
63 
64   }
65 }
66 
67 
68 
69 
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)70 static void xvmc_render_macro_blocks(vo_frame_t *current_image,
71 				     vo_frame_t *backward_ref_image,
72 				     vo_frame_t *forward_ref_image,
73 				     int picture_structure,
74 				     int second_field,
75 				     xvmc_macroblocks_t *macroblocks) {
76   xxmc_driver_t *this           = (xxmc_driver_t *) current_image->driver;
77   xxmc_frame_t  *current_frame  = XXMC_FRAME(current_image);
78   xxmc_frame_t  *forward_frame  = XXMC_FRAME(forward_ref_image);
79   xxmc_frame_t  *backward_frame = XXMC_FRAME(backward_ref_image);
80   int           flags;
81 
82   lprintf ("xvmc_render_macro_blocks\n");
83   lprintf ("slices %d 0x%08lx 0x%08lx 0x%08lx\n",
84 	   macroblocks->slices,
85 	   (long) current_frame, (long) backward_frame,
86 	   (long) forward_frame);
87 
88   flags = second_field;
89 
90   XVMCLOCKDISPLAY( this->display);
91   XvMCRenderSurface(this->display, &this->context, picture_structure,
92 		    current_frame->xvmc_surf,
93 		    forward_frame ? forward_frame->xvmc_surf : NULL,
94 		    backward_frame ? backward_frame->xvmc_surf : NULL,
95                     flags,
96 		    macroblocks->slices, 0, &macroblocks->macro_blocks,
97 		    &macroblocks->blocks);
98   XVMCUNLOCKDISPLAY( this->display);
99 }
100 
101 
102 
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])103 void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type,
104 				int (*mv_field_sel)[2], int *dmvector, int cbp,
105 				int dct_type, vo_frame_t *current_frame,
106 				vo_frame_t *forward_ref_frame,
107 				vo_frame_t *backward_ref_frame, int picture_structure,
108 				int second_field, int (*f_mot_pmv)[2], int (*b_mot_pmv)[2])
109 {
110   xxmc_driver_t        *this                = (xxmc_driver_t *) current_frame->driver;
111   xvmc_macroblocks_t   *mbs                 = &this->macroblocks;
112   int                   top_field_first     = current_frame->top_field_first;
113   int                   picture_coding_type = current_frame->picture_coding_type;
114 
115   mbs->macroblockptr->x = x;
116   mbs->macroblockptr->y = y;
117 
118   if(mb_type & XINE_MACROBLOCK_INTRA) {
119     mbs->macroblockptr->macroblock_type = XVMC_MB_TYPE_INTRA;
120   }
121   else {
122     mbs->macroblockptr->macroblock_type = 0;
123     /* XvMC doesn't support skips */
124     if(!(mb_type & (XINE_MACROBLOCK_MOTION_BACKWARD | XINE_MACROBLOCK_MOTION_FORWARD))) {
125       mb_type |= XINE_MACROBLOCK_MOTION_FORWARD;
126       motion_type = (picture_structure == VO_BOTH_FIELDS) ? XINE_MC_FRAME : XINE_MC_FIELD;
127       mbs->macroblockptr->PMV[0][0][0] = 0;
128       mbs->macroblockptr->PMV[0][0][1] = 0;
129     }
130     else {
131       if(mb_type & XINE_MACROBLOCK_MOTION_BACKWARD) {
132 	mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD;
133 	mbs->macroblockptr->PMV[0][1][0]    = b_mot_pmv[0][0];
134 	mbs->macroblockptr->PMV[0][1][1]    = b_mot_pmv[0][1];
135 	mbs->macroblockptr->PMV[1][1][0]    = b_mot_pmv[1][0];
136 	mbs->macroblockptr->PMV[1][1][1]    = b_mot_pmv[1][1];
137 
138       }
139 
140       if(mb_type & XINE_MACROBLOCK_MOTION_FORWARD) {
141 	mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD;
142 	mbs->macroblockptr->PMV[0][0][0]    = f_mot_pmv[0][0];
143 	mbs->macroblockptr->PMV[0][0][1]    = f_mot_pmv[0][1];
144 	mbs->macroblockptr->PMV[1][0][0]    = f_mot_pmv[1][0];
145 	mbs->macroblockptr->PMV[1][0][1]    = f_mot_pmv[1][1];
146       }
147     }
148 
149     if((mb_type & XINE_MACROBLOCK_PATTERN) && cbp)
150       mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_PATTERN;
151 
152     mbs->macroblockptr->motion_type = motion_type;
153 
154     if(motion_type == XINE_MC_DMV) {
155       int DMV[2][2];
156 
157       if(picture_structure == VO_BOTH_FIELDS) {
158 	calc_DMV(DMV,dmvector, f_mot_pmv[0][0],
159 		 f_mot_pmv[0][1]>>1, picture_structure,
160 		 top_field_first);
161 
162 	mbs->macroblockptr->PMV[1][0][0] = DMV[0][0];
163 	mbs->macroblockptr->PMV[1][0][1] = DMV[0][1];
164 	mbs->macroblockptr->PMV[1][1][0] = DMV[1][0];
165 	mbs->macroblockptr->PMV[1][1][1] = DMV[1][1];
166       }
167       else {
168 	calc_DMV(DMV,dmvector, f_mot_pmv[0][0],
169 		 f_mot_pmv[0][1]>>1, picture_structure,
170 		 top_field_first);
171 
172 	mbs->macroblockptr->PMV[0][1][0] = DMV[0][0];
173 	mbs->macroblockptr->PMV[0][1][1] = DMV[0][1];
174       }
175     }
176 
177     if((motion_type == XINE_MC_FIELD) || (motion_type == XINE_MC_16X8)) {
178       mbs->macroblockptr->motion_vertical_field_select = 0;
179       if(mv_field_sel[0][0])
180 	mbs->macroblockptr->motion_vertical_field_select |= 1;
181       if(mv_field_sel[0][1])
182 	mbs->macroblockptr->motion_vertical_field_select |= 2;
183       if(mv_field_sel[1][0])
184 	mbs->macroblockptr->motion_vertical_field_select |= 4;
185       if(mv_field_sel[1][1])
186 	mbs->macroblockptr->motion_vertical_field_select |= 8;
187     }
188   } /* else of if(mb_type & XINE_MACROBLOCK_INTRA) */
189 
190   mbs->macroblockptr->index = ((unsigned long)mbs->xine_mc.blockptr -
191 			       (unsigned long)mbs->xine_mc.blockbaseptr) >> 7;
192 
193   mbs->macroblockptr->dct_type = dct_type;
194   mbs->macroblockptr->coded_block_pattern = cbp;
195 
196   cbp &= 0x3F;
197   mbs->macroblockptr->coded_block_pattern = cbp;
198 
199   while(cbp) {
200     if(cbp & 1) mbs->macroblockptr->index--;
201     cbp >>= 1;
202   }
203 
204 #ifdef PRINTDATA
205   printf("\n");
206   printf("-- %04d %04d %02x %02x %02x %02x",mbs->macroblockptr->x,mbs->macroblockptr->y,mbs->macroblockptr->macroblock_type,
207 	 mbs->macroblockptr->motion_type,mbs->macroblockptr->motion_vertical_field_select,mbs->macroblockptr->dct_type);
208   printf(" [%04d %04d %04d %04d %04d %04d %04d %04d] ",
209 	 mbs->macroblockptr->PMV[0][0][0],mbs->macroblockptr->PMV[0][0][1],mbs->macroblockptr->PMV[0][1][0],mbs->macroblockptr->PMV[0][1][1],
210 	 mbs->macroblockptr->PMV[1][0][0],mbs->macroblockptr->PMV[1][0][1],mbs->macroblockptr->PMV[1][1][0],mbs->macroblockptr->PMV[1][1][1]);
211 
212   printf(" %04d %04x\n",mbs->macroblockptr->index,mbs->macroblockptr->coded_block_pattern);
213 #endif
214 
215   mbs->num_blocks++;
216   mbs->macroblockptr++;
217 
218   if(mbs->num_blocks == mbs->slices) {
219 #ifdef PRINTDATA
220     printf("macroblockptr %lx",  mbs->macroblockptr);
221     printf("** RenderSurface %04d %04x\n",picture_structure,
222 	   second_field ? XVMC_SECOND_FIELD : 0);
223     fflush(stdout);
224 #endif
225 #ifdef PRINTFRAME
226     printf("  target %08x past %08x future %08x\n",
227 	   current_frame,
228 	   forward_ref_frame,
229 	   backward_ref_frame);
230 #endif
231 #ifdef PRINTFRAME
232     if (picture_coding_type == XINE_PICT_P_TYPE)
233       printf(" coding type P_TYPE\n");
234     if (picture_coding_type == XINE_PICT_I_TYPE)
235       printf(" coding type I_TYPE\n");
236     if (picture_coding_type == XINE_PICT_B_TYPE)
237       printf(" coding type B_TYPE\n");
238     if (picture_coding_type == XINE_PICT_D_TYPE)
239       printf(" coding type D_TYPE\n");
240     fflush(stdout);
241 #endif
242 
243     xvmc_render_macro_blocks(
244 			     current_frame,
245 			     (picture_coding_type == XINE_PICT_B_TYPE) ?
246 			     backward_ref_frame : NULL,
247 			     (picture_coding_type != XINE_PICT_I_TYPE) ?
248 			     forward_ref_frame : NULL,
249 			     picture_structure,
250 			     second_field ? XVMC_SECOND_FIELD : 0,
251 			     mbs);
252 
253     mbs->num_blocks       = 0;
254     mbs->macroblockptr    = mbs->macroblockbaseptr;
255     mbs->xine_mc.blockptr = mbs->xine_mc.blockbaseptr;
256   }
257 }
258 
259 
260 
261