Parent Directory
|
Revision Log
Revision 1.2 - (view) (download)
1 : | chl | 1.1 | /************************************************************************** |
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 = ¤t->image; | ||
162 : | pRef = &reference->image; | ||
163 : | |||
164 : | chl | 1.2 | // time = read_counter(); |
165 : | chl | 1.1 | |
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 : | chl | 1.2 | // fprintf(stderr,"[%d,%d] Full ME %lld ticks \n",arg->id,run,read_counter()-time); |
263 : | chl | 1.1 | |
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 : | chl | 1.2 | // time = read_counter(); |
283 : | chl | 1.1 | |
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 : | chl | 1.2 | // fprintf(stderr,"[%d,%d] Full CORR %lld ticks \n",arg->id,run,read_counter()-time); |
307 : | chl | 1.1 | |
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 |