[svn] / branches / dev-api-4 / xvidcore / src / motion / smp_motion_est.c Repository:
ViewVC logotype

Annotation of /branches/dev-api-4/xvidcore/src/motion/smp_motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 851 - (view) (download)
Original Path: trunk/xvidcore/src/motion/smp_motion_est.c

1 : edgomez 851 /**************************************************************************
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 :    
46 :     #ifndef WIN32
47 :     #include <unistd.h>
48 :     #endif
49 :    
50 :     #include "../encoder.h"
51 :     #include "../utils/mbfunctions.h"
52 :     #include "../prediction/mbprediction.h"
53 :     #include "../global.h"
54 :     #include "../utils/timer.h"
55 :     #include "motion.h"
56 :     #include "sad.h"
57 :    
58 :     #include "smp_motion_est.h"
59 :    
60 :     /* global variables for SMP search control, the are not needed anywhere else than here */
61 :    
62 :     pthread_mutex_t me_mutex = PTHREAD_MUTEX_INITIALIZER;
63 :     pthread_cond_t me_inqueue_cond = PTHREAD_COND_INITIALIZER;
64 :     pthread_cond_t me_corrqueue_cond = PTHREAD_COND_INITIALIZER;
65 :     pthread_cond_t me_outqueue_cond = PTHREAD_COND_INITIALIZER;
66 :    
67 :    
68 :     int me_iIntra=0;
69 :     int me_inqueue=0; // input queue
70 :     int me_corrqueue=0; // correction queue
71 :     int me_outqueue=0; // output queue
72 :    
73 :    
74 :     void SMP_correct_pmv(int x, int y, int iWcount, MACROBLOCK* pMBs)
75 :     {
76 :     MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
77 :     VECTOR pmv;
78 :     int k;
79 :    
80 :     switch (pMB->mode) {
81 :    
82 :     case MODE_INTER:
83 :     case MODE_INTER_Q:
84 :     pmv = get_pmv2(pMBs, iWcount, 0, x, y, 0);
85 :     pMB->pmvs[0].x = pMB->mvs[0].x - pmv.x;
86 :     pMB->pmvs[0].y = pMB->mvs[0].y - pmv.y;
87 :     break;
88 :    
89 :     case MODE_INTER4V:
90 :     for (k=0;k<4;k++) {
91 :     pmv = get_pmv2(pMBs, iWcount, 0, x, y, k);
92 :     pMB->pmvs[k].x = pMB->mvs[k].x - pmv.x;
93 :     pMB->pmvs[k].y = pMB->mvs[k].y - pmv.y;
94 :     }
95 :     break;
96 :    
97 :     default:
98 :     break; /* e.g. everything without prediction, e.g. MODE_INTRA */
99 :     }
100 :     return;
101 :     }
102 :    
103 :     void SMP_MotionEstimationWorker(jobdata *arg)
104 :     {
105 :     const VECTOR zeroMV = { 0, 0 };
106 :    
107 :     // long long time;
108 :     int32_t x, y;
109 :     VECTOR pmv;
110 :    
111 :     globaldata* gdata;
112 :    
113 :     MBParam * pParam;
114 :     FRAMEINFO * current;
115 :     FRAMEINFO * reference;
116 :     IMAGE * pRefH;
117 :     IMAGE * pRefV;
118 :     IMAGE * pRefHV;
119 :     // uint32_t iLimit;
120 :    
121 :     uint32_t iWcount;
122 :     uint32_t iHcount;
123 :     MACROBLOCK * pMBs;
124 :     MACROBLOCK * prevMBs;
125 :     IMAGE * pCurrent;
126 :     IMAGE * pRef;
127 :    
128 :     int minx = arg->minx;
129 :     int maxx = arg->maxx;
130 :     int miny = arg->miny;
131 :     int maxy = arg->maxy;
132 :    
133 :     // int run=0;
134 :     int iIntra;
135 :    
136 :     pthread_mutex_lock(&me_mutex);
137 :     while (1)
138 :     {
139 :     // run++;
140 :     iIntra = 0;
141 :    
142 :     // fprintf(stderr,"[%d,%d] wait inqueue %d init\n",arg->id,run,me_inqueue);
143 :     while (!me_inqueue)
144 :     pthread_cond_wait(&me_inqueue_cond,&me_mutex);
145 :    
146 :     // fprintf(stderr,"[%d,%d] wait inqueue %d done\n",arg->id,run,me_inqueue);
147 :    
148 :     me_inqueue--;
149 :     pthread_mutex_unlock(&me_mutex);
150 :    
151 :     gdata = arg->gdata;
152 :     pParam = gdata->pParam;
153 :     current = gdata->current;
154 :     reference = gdata->reference;
155 :     pRefH = gdata->pRefH;
156 :     pRefV = gdata->pRefV;
157 :     pRefHV = gdata->pRefHV;
158 :     // iLimit = gdata->iLimit;
159 :    
160 :     iWcount = pParam->mb_width;
161 :     iHcount = pParam->mb_height;
162 :     pMBs = current->mbs;
163 :     prevMBs = reference->mbs;
164 :     pCurrent = &current->image;
165 :     pRef = &reference->image;
166 :    
167 :     // time = read_counter();
168 :    
169 :     for (y = miny; y < maxy; y++) {
170 :     for (x = minx; x < maxx; x++) {
171 :    
172 :     MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
173 :    
174 :     pMB->sad16 =
175 :     SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
176 :     x, y, current->motion_flags, current->quant,
177 :     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
178 :     &pMB->pmvs[0]);
179 :    
180 :     if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
181 :     int32_t deviation;
182 :    
183 :     deviation =
184 :     dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
185 :     pParam->edged_width);
186 :    
187 :     if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
188 :     pMB->mode = MODE_INTRA;
189 :     pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
190 :     pMB->mvs[3] = zeroMV;
191 :     pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
192 :     pMB->sad8[3] = 0;
193 :    
194 :     iIntra++;
195 :     continue;
196 :     }
197 :     }
198 :    
199 :     pmv = pMB->pmvs[0];
200 :     if (current->global_flags & XVID_INTER4V)
201 :     if ((!(current->global_flags & XVID_LUMIMASKING) ||
202 :     pMB->dquant == NO_CHANGE)) {
203 :     int32_t sad8 = IMV16X16 * current->quant;
204 :    
205 :     if (sad8 < pMB->sad16)
206 :    
207 :     sad8 += pMB->sad8[0] =
208 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
209 :     pCurrent, 2 * x, 2 * y, pMB->mv16.x,
210 :     pMB->mv16.y, current->motion_flags,
211 :     current->quant, current->fcode, pParam,
212 :     pMBs, prevMBs, &pMB->mvs[0],
213 :     &pMB->pmvs[0]);
214 :    
215 :     if (sad8 < pMB->sad16)
216 :     sad8 += pMB->sad8[1] =
217 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
218 :     pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,
219 :     pMB->mv16.y, current->motion_flags,
220 :     current->quant, current->fcode, pParam,
221 :     pMBs, prevMBs, &pMB->mvs[1],
222 :     &pMB->pmvs[1]);
223 :    
224 :     if (sad8 < pMB->sad16)
225 :     sad8 += pMB->sad8[2] =
226 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
227 :     pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,
228 :     pMB->mv16.y, current->motion_flags,
229 :     current->quant, current->fcode, pParam,
230 :     pMBs, prevMBs, &pMB->mvs[2],
231 :     &pMB->pmvs[2]);
232 :    
233 :     if (sad8 < pMB->sad16)
234 :     sad8 += pMB->sad8[3] =
235 :     SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
236 :     pCurrent, 2 * x + 1, 2 * y + 1,
237 :     pMB->mv16.x, pMB->mv16.y,
238 :     current->motion_flags, current->quant,
239 :     current->fcode, pParam, pMBs, prevMBs,
240 :     &pMB->mvs[3], &pMB->pmvs[3]);
241 :    
242 :     /* decide: MODE_INTER or MODE_INTER4V
243 :     mpeg4: if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
244 :     */
245 :    
246 :     if (sad8 < pMB->sad16) {
247 :     pMB->mode = MODE_INTER4V;
248 :     pMB->sad8[0] *= 4;
249 :     pMB->sad8[1] *= 4;
250 :     pMB->sad8[2] *= 4;
251 :     pMB->sad8[3] *= 4;
252 :     continue;
253 :     }
254 :    
255 :     }
256 :    
257 :     pMB->mode = MODE_INTER;
258 :     pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3] are not needed for INTER */
259 :     pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
260 :     pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
261 :    
262 :     }
263 :     } /* end of x/y loop */
264 :    
265 :     // fprintf(stderr,"[%d,%d] Full ME %lld ticks \n",arg->id,run,read_counter()-time);
266 :    
267 :     pthread_mutex_lock(&me_mutex);
268 :    
269 :     me_corrqueue--; // the last to finish wakes the others to start correction
270 :     me_iIntra += iIntra;
271 :    
272 :     if (me_corrqueue==0)
273 :     {
274 :     // fprintf(stderr,"[%d,%d] corrqueue %d waking neighbours\n",arg->id,run,me_corrqueue);
275 :     pthread_cond_broadcast(&me_corrqueue_cond);
276 :     }
277 :    
278 :     // fprintf(stderr,"[%d,%d] wait corrqueue %d init\n",arg->id,run,me_corrqueue);
279 :    
280 :     while (me_corrqueue)
281 :     pthread_cond_wait(&me_corrqueue_cond,&me_mutex);
282 :    
283 :     // fprintf(stderr,"[%d,%d] wait corrqueue %d done\n",arg->id,run,me_corrqueue);
284 :    
285 :     // time = read_counter();
286 :    
287 :     // if (me_iIntra <= iLimit)
288 :     // {
289 :     // pthread_mutex_unlock(&me_mutex);
290 :    
291 :     if (minx!=0)
292 :     for (y=miny; y<maxy; y++)
293 :     SMP_correct_pmv(minx, y,iWcount,pMBs);
294 :     if (maxx!=iWcount)
295 :     for (y=miny; y<maxy; y++)
296 :     SMP_correct_pmv(maxx-1,y,iWcount,pMBs);
297 :    
298 :     if (miny!=0)
299 :     for (x=minx;x<maxx; x++)
300 :     SMP_correct_pmv(x,miny, iWcount,pMBs);
301 :    
302 :     if (maxy!=iHcount)
303 :     for (x=minx;x<maxx; x++)
304 :     SMP_correct_pmv(x,maxy-1,iWcount,pMBs);
305 :    
306 :     // pthread_mutex_lock(&me_mutex);
307 :     // }
308 :    
309 :     // fprintf(stderr,"[%d,%d] Full CORR %lld ticks \n",arg->id,run,read_counter()-time);
310 :    
311 :     me_outqueue--;
312 :    
313 :     if (me_outqueue==0) // the last to finish wakes the master
314 :     pthread_cond_signal(&me_outqueue_cond);
315 :    
316 :     // fprintf(stderr,"[%d,%d] wait outqueue %d init\n",arg->id,run,me_outqueue);
317 :    
318 :     // while (me_outqueue)
319 :     // pthread_cond_wait(&me_outqueue_cond,&me_mutex);
320 :    
321 :     // fprintf(stderr,"[%d,%d] wait outqueue %d done\n",arg->id,run,me_outqueue);
322 :    
323 :     } /* end of while(1) */
324 :     pthread_mutex_unlock(&me_mutex);
325 :     }
326 :    
327 :     bool
328 :     SMP_MotionEstimation(MBParam * const pParam,
329 :     FRAMEINFO * const current,
330 :     FRAMEINFO * const reference,
331 :     const IMAGE * const pRefH,
332 :     const IMAGE * const pRefV,
333 :     const IMAGE * const pRefHV,
334 :     const uint32_t iLimit)
335 :     {
336 :     int i;
337 :     static int threadscreated=0;
338 :    
339 :     const int iWcount = pParam->mb_width;
340 :     const int iHcount = pParam->mb_height;
341 :    
342 :     static globaldata gdata;
343 :     static jobdata jdata[MAXNUMTHREADS];
344 :     static pthread_t me_thread[MAXNUMTHREADS];
345 :    
346 :     gdata.pParam = pParam;
347 :     gdata.reference = reference;
348 :     gdata.current = current;
349 :     gdata.pRefH = pRefH;
350 :     gdata.pRefV = pRefV;
351 :     gdata.pRefHV = pRefHV;
352 :     // gdata.iLimit = iLimit;
353 :    
354 :     if (sadInit)
355 :     (*sadInit) ();
356 :    
357 :     pthread_mutex_lock(&me_mutex);
358 :     me_iIntra=0;
359 :     me_inqueue=pParam->num_threads;
360 :     me_corrqueue=pParam->num_threads;
361 :     me_outqueue=pParam->num_threads;
362 :    
363 :     if (!threadscreated)
364 :     {
365 :     for (i=0;i<pParam->num_threads;i++) { /* split domain into NUMTHREADS parts */
366 :    
367 :     jdata[i].id = i;
368 :     jdata[i].minx = i*iWcount/pParam->num_threads;
369 :     jdata[i].maxx = (i+1)*iWcount/pParam->num_threads;
370 :     jdata[i].miny = 0;
371 :     jdata[i].maxy = iHcount;
372 :     jdata[i].gdata = &gdata;
373 :    
374 :     pthread_create(&me_thread[i],NULL,
375 :     (void*)SMP_MotionEstimationWorker,(void*)&jdata[i]);
376 :     }
377 :     threadscreated=1;
378 :     }
379 :    
380 :     pthread_cond_broadcast(&me_inqueue_cond); // start working
381 :    
382 :     while (me_outqueue)
383 :     pthread_cond_wait(&me_outqueue_cond,&me_mutex);
384 :    
385 :     if (me_iIntra > iLimit)
386 :     {
387 :     pthread_mutex_unlock(&me_mutex);
388 :     return 1;
389 :     }
390 :    
391 :     pthread_mutex_unlock(&me_mutex);
392 :     return 0;
393 :     }
394 :    
395 :     #endif

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