[svn] / trunk / xvidcore / src / motion / smp_motion_est.c Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/src/motion/smp_motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 258 - (view) (download)

1 : chl 258 /**************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 :     * multithreaded motion estimation
5 :     *
6 :     * This program is an implementation of a part of one or more MPEG-4
7 :     * Video tools as specified in ISO/IEC 14496-2 standard. Those intending
8 :     * to use this software module in hardware or software products are
9 :     * advised that its use may infringe existing patents or copyrights, and
10 :     * any such use would be at such party's own risk. The original
11 :     * developer of this software module and his/her company, and subsequent
12 :     * editors and their companies, will have no liability for use of this
13 :     * software or modifications or derivatives thereof.
14 :     *
15 :     * This program is free software; you can redistribute it and/or modify
16 :     * it under the terms of the GNU General Public License as published by
17 :     * the Free Software Foundation; either version 2 of the License, or
18 :     * (at your option) any later version.
19 :     *
20 :     * This program is distributed in the hope that it will be useful,
21 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 :     * GNU General Public License for more details.
24 :     *
25 :     * You should have received a copy of the GNU General Public License
26 :     * along with this program; if not, write to the Free Software
27 :     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 :     *
29 :     *************************************************************************/
30 :    
31 :    
32 :     /* WARNING !
33 :     * This is early alpha code, only published for debugging and testing
34 :     * I cannot garantee that it will not break compiliing, encoding
35 :     * or your marriage etc. YOU HAVE BEEN WARNED!
36 :     */
37 :    
38 :     #ifdef _SMP
39 :    
40 :     #include <stdio.h>
41 :     #include <stdlib.h>
42 :    
43 :     #include <pthread.h>
44 :     #include <signal.h>
45 :     #include <unistd.h>
46 :    
47 :     #include "../encoder.h"
48 :     #include "../utils/mbfunctions.h"
49 :     #include "../prediction/mbprediction.h"
50 :     #include "../global.h"
51 :     #include "../utils/timer.h"
52 :     #include "motion.h"
53 :     #include "sad.h"
54 :    
55 :     #include "smp_motion_est.h"
56 :    
57 :     /* global variables for SMP search control, the are not needed anywhere else than here */
58 :    
59 :     pthread_mutex_t me_mutex = PTHREAD_MUTEX_INITIALIZER;
60 :     pthread_cond_t me_inqueue_cond = PTHREAD_COND_INITIALIZER;
61 :     pthread_cond_t me_corrqueue_cond = PTHREAD_COND_INITIALIZER;
62 :     pthread_cond_t me_outqueue_cond = PTHREAD_COND_INITIALIZER;
63 :    
64 :    
65 :     int me_iIntra=0;
66 :     int me_inqueue=0; // input queue
67 :     int me_corrqueue=0; // correction queue
68 :     int me_outqueue=0; // output queue
69 :    
70 :    
71 :     void SMP_correct_pmv(int x, int y, int iWcount, MACROBLOCK* pMBs)
72 :     {
73 :     MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
74 :     VECTOR pmv;
75 :     int k;
76 :    
77 :     switch (pMB->mode) {
78 :    
79 :     case MODE_INTER:
80 :     case MODE_INTER_Q:
81 :     pmv = get_pmv(pMBs, x, y, iWcount, 0);
82 :     pMB->pmvs[0].x = pMB->mvs[0].x - pmv.x;
83 :     pMB->pmvs[0].y = pMB->mvs[0].y - pmv.y;
84 :     break;
85 :    
86 :     case MODE_INTER4V:
87 :     for (k=0;k<4;k++) {
88 :     pmv = get_pmv(pMBs, x, y, iWcount, k);
89 :     pMB->pmvs[k].x = pMB->mvs[k].x - pmv.x;
90 :     pMB->pmvs[k].y = pMB->mvs[k].y - pmv.y;
91 :     }
92 :     break;
93 :    
94 :     default:
95 :     break; /* e.g. everything without prediction, e.g. MODE_INTRA */
96 :     }
97 :     return;
98 :     }
99 :    
100 :     void SMP_MotionEstimationWorker(jobdata *arg)
101 :     {
102 :     const VECTOR zeroMV = { 0, 0 };
103 :    
104 :     // long long time;
105 :     int32_t x, y;
106 :     VECTOR pmv;
107 :    
108 :     globaldata* gdata;
109 :    
110 :     MBParam * pParam;
111 :     FRAMEINFO * current;
112 :     FRAMEINFO * reference;
113 :     IMAGE * pRefH;
114 :     IMAGE * pRefV;
115 :     IMAGE * pRefHV;
116 :     // uint32_t iLimit;
117 :    
118 :     uint32_t iWcount;
119 :     uint32_t iHcount;
120 :     MACROBLOCK * pMBs;
121 :     MACROBLOCK * prevMBs;
122 :     IMAGE * pCurrent;
123 :     IMAGE * pRef;
124 :    
125 :     int minx = arg->minx;
126 :     int maxx = arg->maxx;
127 :     int miny = arg->miny;
128 :     int maxy = arg->maxy;
129 :    
130 :     // int run=0;
131 :     int iIntra;
132 :    
133 :     pthread_mutex_lock(&me_mutex);
134 :     while (1)
135 :     {
136 :     // run++;
137 :     iIntra = 0;
138 :    
139 :     // fprintf(stderr,"[%d,%d] wait inqueue %d init\n",arg->id,run,me_inqueue);
140 :     while (!me_inqueue)
141 :     pthread_cond_wait(&me_inqueue_cond,&me_mutex);
142 :    
143 :     // fprintf(stderr,"[%d,%d] wait inqueue %d done\n",arg->id,run,me_inqueue);
144 :    
145 :     me_inqueue--;
146 :     pthread_mutex_unlock(&me_mutex);
147 :    
148 :     gdata = arg->gdata;
149 :     pParam = gdata->pParam;
150 :     current = gdata->current;
151 :     reference = gdata->reference;
152 :     pRefH = gdata->pRefH;
153 :     pRefV = gdata->pRefV;
154 :     pRefHV = gdata->pRefHV;
155 :     // iLimit = gdata->iLimit;
156 :    
157 :     iWcount = pParam->mb_width;
158 :     iHcount = pParam->mb_height;
159 :     pMBs = current->mbs;
160 :     prevMBs = reference->mbs;
161 :     pCurrent = &current->image;
162 :     pRef = &reference->image;
163 :    
164 :     // time = read_tsc();
165 :    
166 :     for (y = miny; y < maxy; y++) {
167 :     for (x = minx; x < maxx; x++) {
168 :    
169 :     MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
170 :    
171 :     pMB->sad16 =
172 :     SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
173 :     x, y, current->motion_flags, current->quant,
174 :     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
175 :     &pMB->pmvs[0]);
176 :    
177 :     if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
178 :     int32_t deviation;
179 :    
180 :     deviation =
181 :     dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
182 :     pParam->edged_width);
183 :    
184 :     if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
185 :     pMB->mode = MODE_INTRA;
186 :     pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
187 :     pMB->mvs[3] = zeroMV;
188 :     pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
189 :     pMB->sad8[3] = 0;
190 :    
191 :     iIntra++;
192 :     continue;
193 :     }
194 :     }
195 :    
196 :     pmv = pMB->pmvs[0];
197 :     if (current->global_flags & XVID_INTER4V)
198 :     if ((!(current->global_flags & XVID_LUMIMASKING) ||
199 :     pMB->dquant == NO_CHANGE)) {
200 :     int32_t sad8 = IMV16X16 * current->quant;
201 :    
202 :     if (sad8 < pMB->sad16)
203 :    
204 :     sad8 += pMB->sad8[0] =
205 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
206 :     pCurrent, 2 * x, 2 * y, pMB->mv16.x,
207 :     pMB->mv16.y, current->motion_flags,
208 :     current->quant, current->fcode, pParam,
209 :     pMBs, prevMBs, &pMB->mvs[0],
210 :     &pMB->pmvs[0]);
211 :    
212 :     if (sad8 < pMB->sad16)
213 :     sad8 += pMB->sad8[1] =
214 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
215 :     pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,
216 :     pMB->mv16.y, current->motion_flags,
217 :     current->quant, current->fcode, pParam,
218 :     pMBs, prevMBs, &pMB->mvs[1],
219 :     &pMB->pmvs[1]);
220 :    
221 :     if (sad8 < pMB->sad16)
222 :     sad8 += pMB->sad8[2] =
223 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
224 :     pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,
225 :     pMB->mv16.y, current->motion_flags,
226 :     current->quant, current->fcode, pParam,
227 :     pMBs, prevMBs, &pMB->mvs[2],
228 :     &pMB->pmvs[2]);
229 :    
230 :     if (sad8 < pMB->sad16)
231 :     sad8 += pMB->sad8[3] =
232 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
233 :     pCurrent, 2 * x + 1, 2 * y + 1,
234 :     pMB->mv16.x, pMB->mv16.y,
235 :     current->motion_flags, current->quant,
236 :     current->fcode, pParam, pMBs, prevMBs,
237 :     &pMB->mvs[3], &pMB->pmvs[3]);
238 :    
239 :     /* decide: MODE_INTER or MODE_INTER4V
240 :     mpeg4: if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
241 :     */
242 :    
243 :     if (sad8 < pMB->sad16) {
244 :     pMB->mode = MODE_INTER4V;
245 :     pMB->sad8[0] *= 4;
246 :     pMB->sad8[1] *= 4;
247 :     pMB->sad8[2] *= 4;
248 :     pMB->sad8[3] *= 4;
249 :     continue;
250 :     }
251 :    
252 :     }
253 :    
254 :     pMB->mode = MODE_INTER;
255 :     pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3] are not needed for INTER */
256 :     pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
257 :     pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
258 :    
259 :     }
260 :     } /* end of x/y loop */
261 :    
262 :     // fprintf(stderr,"[%d,%d] Full ME %lld ticks \n",arg->id,run,read_tsc()-time);
263 :    
264 :     pthread_mutex_lock(&me_mutex);
265 :    
266 :     me_corrqueue--; // the last to finish wakes the others to start correction
267 :     me_iIntra += iIntra;
268 :    
269 :     if (me_corrqueue==0)
270 :     {
271 :     // fprintf(stderr,"[%d,%d] corrqueue %d waking neighbours\n",arg->id,run,me_corrqueue);
272 :     pthread_cond_broadcast(&me_corrqueue_cond);
273 :     }
274 :    
275 :     // fprintf(stderr,"[%d,%d] wait corrqueue %d init\n",arg->id,run,me_corrqueue);
276 :    
277 :     while (me_corrqueue)
278 :     pthread_cond_wait(&me_corrqueue_cond,&me_mutex);
279 :    
280 :     // fprintf(stderr,"[%d,%d] wait corrqueue %d done\n",arg->id,run,me_corrqueue);
281 :    
282 :     // time = read_tsc();
283 :    
284 :     // if (me_iIntra <= iLimit)
285 :     // {
286 :     // pthread_mutex_unlock(&me_mutex);
287 :    
288 :     if (minx!=0)
289 :     for (y=miny; y<maxy; y++)
290 :     SMP_correct_pmv(minx, y,iWcount,pMBs);
291 :     if (maxx!=iWcount)
292 :     for (y=miny; y<maxy; y++)
293 :     SMP_correct_pmv(maxx-1,y,iWcount,pMBs);
294 :    
295 :     if (miny!=0)
296 :     for (x=minx;x<maxx; x++)
297 :     SMP_correct_pmv(x,miny, iWcount,pMBs);
298 :    
299 :     if (maxy!=iHcount)
300 :     for (x=minx;x<maxx; x++)
301 :     SMP_correct_pmv(x,maxy-1,iWcount,pMBs);
302 :    
303 :     // pthread_mutex_lock(&me_mutex);
304 :     // }
305 :    
306 :     // fprintf(stderr,"[%d,%d] Full CORR %lld ticks \n",arg->id,run,read_tsc()-time);
307 :    
308 :     me_outqueue--;
309 :    
310 :     if (me_outqueue==0) // the last to finish wakes the master
311 :     pthread_cond_signal(&me_outqueue_cond);
312 :    
313 :     // fprintf(stderr,"[%d,%d] wait outqueue %d init\n",arg->id,run,me_outqueue);
314 :    
315 :     // while (me_outqueue)
316 :     // pthread_cond_wait(&me_outqueue_cond,&me_mutex);
317 :    
318 :     // fprintf(stderr,"[%d,%d] wait outqueue %d done\n",arg->id,run,me_outqueue);
319 :    
320 :     } /* end of while(1) */
321 :     pthread_mutex_unlock(&me_mutex);
322 :     }
323 :    
324 :     bool
325 :     SMP_MotionEstimation(MBParam * const pParam,
326 :     FRAMEINFO * const current,
327 :     FRAMEINFO * const reference,
328 :     const IMAGE * const pRefH,
329 :     const IMAGE * const pRefV,
330 :     const IMAGE * const pRefHV,
331 :     const uint32_t iLimit)
332 :     {
333 :     int i;
334 :     static int threadscreated=0;
335 :    
336 :     const int iWcount = pParam->mb_width;
337 :     const int iHcount = pParam->mb_height;
338 :    
339 :     static globaldata gdata;
340 :     static jobdata jdata[MAXNUMTHREADS];
341 :     static pthread_t me_thread[MAXNUMTHREADS];
342 :    
343 :     gdata.pParam = pParam;
344 :     gdata.reference = reference;
345 :     gdata.current = current;
346 :     gdata.pRefH = pRefH;
347 :     gdata.pRefV = pRefV;
348 :     gdata.pRefHV = pRefHV;
349 :     // gdata.iLimit = iLimit;
350 :    
351 :     if (sadInit)
352 :     (*sadInit) ();
353 :    
354 :     pthread_mutex_lock(&me_mutex);
355 :     me_iIntra=0;
356 :     me_inqueue=NUMTHREADS;
357 :     me_corrqueue=NUMTHREADS;
358 :     me_outqueue=NUMTHREADS;
359 :    
360 :     if (!threadscreated)
361 :     {
362 :     for (i=0;i<NUMTHREADS;i++) { /* split domain into NUMTHREADS parts */
363 :    
364 :     jdata[i].id = i;
365 :     jdata[i].minx = i*iWcount/NUMTHREADS;
366 :     jdata[i].maxx = (i+1)*iWcount/NUMTHREADS;
367 :     jdata[i].miny = 0;
368 :     jdata[i].maxy = iHcount;
369 :     jdata[i].gdata = &gdata;
370 :    
371 :     pthread_create(&me_thread[i],NULL,
372 :     (void*)SMP_MotionEstimationWorker,(void*)&jdata[i]);
373 :     }
374 :     threadscreated=1;
375 :     }
376 :    
377 :     pthread_cond_broadcast(&me_inqueue_cond); // start working
378 :    
379 :     while (me_outqueue)
380 :     pthread_cond_wait(&me_outqueue_cond,&me_mutex);
381 :    
382 :     if (me_iIntra > iLimit)
383 :     {
384 :     pthread_mutex_unlock(&me_mutex);
385 :     return 1;
386 :     }
387 :    
388 :     pthread_mutex_unlock(&me_mutex);
389 :     return 0;
390 :     }
391 :    
392 :     #endif

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4