00001
00002
00003
00004
00005
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include "pullup.h"
00010 #include "config.h"
00011 #include "../mm_arch.h"
00012
00013
00014
00015 #ifdef HAVE_MMX
00016 static int diff_y_mmx(unsigned char *a, unsigned char *b, int s)
00017 {
00018 int ret;
00019 asm volatile (
00020 "movl $4, %%ecx \n\t"
00021 "pxor %%mm4, %%mm4 \n\t"
00022 "pxor %%mm7, %%mm7 \n\t"
00023
00024 ASMALIGN(4)
00025 "1: \n\t"
00026
00027 "movq (%%"REG_S"), %%mm0 \n\t"
00028 "movq (%%"REG_S"), %%mm2 \n\t"
00029 "add %%"REG_a", %%"REG_S" \n\t"
00030 "movq (%%"REG_D"), %%mm1 \n\t"
00031 "add %%"REG_a", %%"REG_D" \n\t"
00032 "psubusb %%mm1, %%mm2 \n\t"
00033 "psubusb %%mm0, %%mm1 \n\t"
00034 "movq %%mm2, %%mm0 \n\t"
00035 "movq %%mm1, %%mm3 \n\t"
00036 "punpcklbw %%mm7, %%mm0 \n\t"
00037 "punpcklbw %%mm7, %%mm1 \n\t"
00038 "punpckhbw %%mm7, %%mm2 \n\t"
00039 "punpckhbw %%mm7, %%mm3 \n\t"
00040 "paddw %%mm0, %%mm4 \n\t"
00041 "paddw %%mm1, %%mm4 \n\t"
00042 "paddw %%mm2, %%mm4 \n\t"
00043 "paddw %%mm3, %%mm4 \n\t"
00044
00045 "decl %%ecx \n\t"
00046 "jnz 1b \n\t"
00047
00048 "movq %%mm4, %%mm3 \n\t"
00049 "punpcklwd %%mm7, %%mm4 \n\t"
00050 "punpckhwd %%mm7, %%mm3 \n\t"
00051 "paddd %%mm4, %%mm3 \n\t"
00052 "movd %%mm3, %%eax \n\t"
00053 "psrlq $32, %%mm3 \n\t"
00054 "movd %%mm3, %%edx \n\t"
00055 "addl %%edx, %%eax \n\t"
00056 "emms \n\t"
00057 : "=a" (ret)
00058 : "S" (a), "D" (b), "a" (s)
00059 : "%ecx", "%edx"
00060 );
00061 return ret;
00062 }
00063
00064 static int licomb_y_mmx(unsigned char *a, unsigned char *b, int s)
00065 {
00066 int ret;
00067 asm volatile (
00068 "movl $4, %%ecx \n\t"
00069 "pxor %%mm6, %%mm6 \n\t"
00070 "pxor %%mm7, %%mm7 \n\t"
00071 "sub %%"REG_a", %%"REG_D" \n\t"
00072
00073 ASMALIGN(4)
00074 "2: \n\t"
00075
00076 "movq (%%"REG_D"), %%mm0 \n\t"
00077 "movq (%%"REG_D"), %%mm1 \n\t"
00078 "punpcklbw %%mm7, %%mm0 \n\t"
00079 "movq (%%"REG_D",%%"REG_a"), %%mm2 \n\t"
00080 "punpcklbw %%mm7, %%mm1 \n\t"
00081 "punpcklbw %%mm7, %%mm2 \n\t"
00082 "paddw %%mm0, %%mm0 \n\t"
00083 "paddw %%mm2, %%mm1 \n\t"
00084 "movq %%mm0, %%mm2 \n\t"
00085 "psubusw %%mm1, %%mm0 \n\t"
00086 "psubusw %%mm2, %%mm1 \n\t"
00087 "paddw %%mm0, %%mm6 \n\t"
00088 "paddw %%mm1, %%mm6 \n\t"
00089
00090 "movq (%%"REG_S"), %%mm0 \n\t"
00091 "movq (%%"REG_D"), %%mm1 \n\t"
00092 "punpckhbw %%mm7, %%mm0 \n\t"
00093 "movq (%%"REG_D",%%"REG_a"), %%mm2 \n\t"
00094 "punpckhbw %%mm7, %%mm1 \n\t"
00095 "punpckhbw %%mm7, %%mm2 \n\t"
00096 "paddw %%mm0, %%mm0 \n\t"
00097 "paddw %%mm2, %%mm1 \n\t"
00098 "movq %%mm0, %%mm2 \n\t"
00099 "psubusw %%mm1, %%mm0 \n\t"
00100 "psubusw %%mm2, %%mm1 \n\t"
00101 "paddw %%mm0, %%mm6 \n\t"
00102 "paddw %%mm1, %%mm6 \n\t"
00103
00104 "movq (%%"REG_D",%%"REG_a"), %%mm0 \n\t"
00105 "movq (%%"REG_S"), %%mm1 \n\t"
00106 "punpcklbw %%mm7, %%mm0 \n\t"
00107 "movq (%%"REG_S",%%"REG_a"), %%mm2 \n\t"
00108 "punpcklbw %%mm7, %%mm1 \n\t"
00109 "punpcklbw %%mm7, %%mm2 \n\t"
00110 "paddw %%mm0, %%mm0 \n\t"
00111 "paddw %%mm2, %%mm1 \n\t"
00112 "movq %%mm0, %%mm2 \n\t"
00113 "psubusw %%mm1, %%mm0 \n\t"
00114 "psubusw %%mm2, %%mm1 \n\t"
00115 "paddw %%mm0, %%mm6 \n\t"
00116 "paddw %%mm1, %%mm6 \n\t"
00117
00118 "movq (%%"REG_D",%%"REG_a"), %%mm0 \n\t"
00119 "movq (%%"REG_S"), %%mm1 \n\t"
00120 "punpckhbw %%mm7, %%mm0 \n\t"
00121 "movq (%%"REG_S",%%"REG_a"), %%mm2 \n\t"
00122 "punpckhbw %%mm7, %%mm1 \n\t"
00123 "punpckhbw %%mm7, %%mm2 \n\t"
00124 "paddw %%mm0, %%mm0 \n\t"
00125 "paddw %%mm2, %%mm1 \n\t"
00126 "movq %%mm0, %%mm2 \n\t"
00127 "psubusw %%mm1, %%mm0 \n\t"
00128 "psubusw %%mm2, %%mm1 \n\t"
00129 "paddw %%mm0, %%mm6 \n\t"
00130 "paddw %%mm1, %%mm6 \n\t"
00131
00132 "add %%"REG_a", %%"REG_S" \n\t"
00133 "add %%"REG_a", %%"REG_D" \n\t"
00134 "decl %%ecx \n\t"
00135 "jnz 2b \n\t"
00136
00137 "movq %%mm6, %%mm5 \n\t"
00138 "punpcklwd %%mm7, %%mm6 \n\t"
00139 "punpckhwd %%mm7, %%mm5 \n\t"
00140 "paddd %%mm6, %%mm5 \n\t"
00141 "movd %%mm5, %%eax \n\t"
00142 "psrlq $32, %%mm5 \n\t"
00143 "movd %%mm5, %%edx \n\t"
00144 "addl %%edx, %%eax \n\t"
00145
00146 "emms \n\t"
00147 : "=a" (ret)
00148 : "S" (a), "D" (b), "a" (s)
00149 : "%ecx", "%edx"
00150 );
00151 return ret;
00152 }
00153
00154 static int var_y_mmx(unsigned char *a, unsigned char *b, int s)
00155 {
00156 (void) b;
00157 int ret;
00158 asm volatile (
00159 "movl $3, %%ecx \n\t"
00160 "pxor %%mm4, %%mm4 \n\t"
00161 "pxor %%mm7, %%mm7 \n\t"
00162
00163 ASMALIGN(4)
00164 "1: \n\t"
00165
00166 "movq (%%"REG_S"), %%mm0 \n\t"
00167 "movq (%%"REG_S"), %%mm2 \n\t"
00168 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t"
00169 "add %%"REG_a", %%"REG_S" \n\t"
00170 "psubusb %%mm1, %%mm2 \n\t"
00171 "psubusb %%mm0, %%mm1 \n\t"
00172 "movq %%mm2, %%mm0 \n\t"
00173 "movq %%mm1, %%mm3 \n\t"
00174 "punpcklbw %%mm7, %%mm0 \n\t"
00175 "punpcklbw %%mm7, %%mm1 \n\t"
00176 "punpckhbw %%mm7, %%mm2 \n\t"
00177 "punpckhbw %%mm7, %%mm3 \n\t"
00178 "paddw %%mm0, %%mm4 \n\t"
00179 "paddw %%mm1, %%mm4 \n\t"
00180 "paddw %%mm2, %%mm4 \n\t"
00181 "paddw %%mm3, %%mm4 \n\t"
00182
00183 "decl %%ecx \n\t"
00184 "jnz 1b \n\t"
00185
00186 "movq %%mm4, %%mm3 \n\t"
00187 "punpcklwd %%mm7, %%mm4 \n\t"
00188 "punpckhwd %%mm7, %%mm3 \n\t"
00189 "paddd %%mm4, %%mm3 \n\t"
00190 "movd %%mm3, %%eax \n\t"
00191 "psrlq $32, %%mm3 \n\t"
00192 "movd %%mm3, %%edx \n\t"
00193 "addl %%edx, %%eax \n\t"
00194 "emms \n\t"
00195 : "=a" (ret)
00196 : "S" (a), "a" (s)
00197 : "%ecx", "%edx"
00198 );
00199 return 4*ret;
00200 }
00201 #endif
00202
00203 #define ABS(a) (((a)^((a)>>31))-((a)>>31))
00204
00205 static int diff_y(unsigned char *a, unsigned char *b, int s)
00206 {
00207 int i, j, diff=0;
00208 for (i=4; i; i--) {
00209 for (j=0; j<8; j++) diff += ABS(a[j]-b[j]);
00210 a+=s; b+=s;
00211 }
00212 return diff;
00213 }
00214
00215 static int licomb_y(unsigned char *a, unsigned char *b, int s)
00216 {
00217 int i, j, diff=0;
00218 for (i=4; i; i--) {
00219 for (j=0; j<8; j++)
00220 diff += ABS((a[j]<<1) - b[j-s] - b[j])
00221 + ABS((b[j]<<1) - a[j] - a[j+s]);
00222 a+=s; b+=s;
00223 }
00224 return diff;
00225 }
00226
00227 static int qpcomb_y(unsigned char *a, unsigned char *b, int s)
00228 __attribute__ ((unused));
00229
00230 static int qpcomb_y(unsigned char *a, unsigned char *b, int s)
00231 {
00232 int i, j, diff=0;
00233 for (i=4; i; i--) {
00234 for (j=0; j<8; j++)
00235 diff += ABS(a[j] - 3*b[j-s] + 3*a[j+s] - b[j]);
00236 a+=s; b+=s;
00237 }
00238 return diff;
00239 }
00240
00241 #if 0
00242 static int licomb_y_test(unsigned char *a, unsigned char *b, int s)
00243 {
00244 int c = licomb_y(a,b,s);
00245 int m = licomb_y_mmx(a,b,s);
00246 if (c != m) printf("%d != %d\n", c, m);
00247 return m;
00248 }
00249 #endif
00250
00251 static int var_y(unsigned char *a, unsigned char *b, int s)
00252 {
00253 int i, j, var=0;
00254 for (i=3; i; i--) {
00255 for (j=0; j<8; j++) {
00256 var += ABS(a[j]-a[j+s]);
00257 }
00258 a+=s; b+=s;
00259 }
00260 return 4*var;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 static void alloc_buffer(struct pullup_context *c, struct pullup_buffer *b)
00272 {
00273 int i;
00274 if (b->planes) return;
00275 b->planes = calloc(c->nplanes, sizeof(unsigned char *));
00276 for (i = 0; i < c->nplanes; i++) {
00277 b->planes[i] = malloc(c->h[i]*c->stride[i]);
00278
00279 memset(b->planes[i], c->background[i], c->h[i]*c->stride[i]);
00280 }
00281 }
00282
00283 struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity)
00284 {
00285 if (!b) return 0;
00286 if ((parity+1) & 1) b->lock[0]++;
00287 if ((parity+1) & 2) b->lock[1]++;
00288 return b;
00289 }
00290
00291 void pullup_release_buffer(struct pullup_buffer *b, int parity)
00292 {
00293 if (!b) return;
00294 if ((parity+1) & 1) b->lock[0]--;
00295 if ((parity+1) & 2) b->lock[1]--;
00296 }
00297
00298 struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity)
00299 {
00300 int i;
00301
00302
00303 if (parity < 2 && c->last && parity != c->last->parity
00304 && !c->last->buffer->lock[parity]) {
00305 alloc_buffer(c, c->last->buffer);
00306 return pullup_lock_buffer(c->last->buffer, parity);
00307 }
00308
00309
00310 for (i = 0; i < c->nbuffers; i++) {
00311 if (c->buffers[i].lock[0]) continue;
00312 if (c->buffers[i].lock[1]) continue;
00313 alloc_buffer(c, &c->buffers[i]);
00314 return pullup_lock_buffer(&c->buffers[i], parity);
00315 }
00316
00317 if (parity == 2) return 0;
00318
00319
00320 for (i = 0; i < c->nbuffers; i++) {
00321 if (((parity+1) & 1) && c->buffers[i].lock[0]) continue;
00322 if (((parity+1) & 2) && c->buffers[i].lock[1]) continue;
00323 alloc_buffer(c, &c->buffers[i]);
00324 return pullup_lock_buffer(&c->buffers[i], parity);
00325 }
00326
00327 return 0;
00328 }
00329
00330
00331
00332
00333
00334
00335 static void compute_metric(struct pullup_context *c,
00336 struct pullup_field *fa, int pa,
00337 struct pullup_field *fb, int pb,
00338 int (*func)(unsigned char *, unsigned char *, int), int *dest)
00339 {
00340 unsigned char *a, *b;
00341 int x, y;
00342 int mp = c->metric_plane;
00343 int xstep = c->bpp[mp];
00344 int ystep = c->stride[mp]<<3;
00345 int s = c->stride[mp]<<1;
00346 int w = c->metric_w*xstep;
00347
00348 if (!fa->buffer || !fb->buffer) return;
00349
00350
00351 if (fa->buffer == fb->buffer && pa == pb) {
00352 memset(dest, 0, c->metric_len * sizeof(int));
00353 return;
00354 }
00355
00356 a = fa->buffer->planes[mp] + pa * c->stride[mp] + c->metric_offset;
00357 b = fb->buffer->planes[mp] + pb * c->stride[mp] + c->metric_offset;
00358
00359 for (y = c->metric_h; y; y--) {
00360 for (x = 0; x < w; x += xstep) {
00361 *dest++ = func(a + x, b + x, s);
00362 }
00363 a += ystep; b += ystep;
00364 }
00365 }
00366
00367
00368
00369
00370
00371 static void alloc_metrics(struct pullup_context *c, struct pullup_field *f)
00372 {
00373 f->diffs = calloc(c->metric_len, sizeof(int));
00374 f->comb = calloc(c->metric_len, sizeof(int));
00375 f->var = calloc(c->metric_len, sizeof(int));
00376
00377 }
00378
00379 static struct pullup_field *make_field_queue(struct pullup_context *c, int len)
00380 {
00381 struct pullup_field *head, *f;
00382 f = head = calloc(1, sizeof(struct pullup_field));
00383 alloc_metrics(c, f);
00384 for (; len > 0; len--) {
00385 f->next = calloc(1, sizeof(struct pullup_field));
00386 f->next->prev = f;
00387 f = f->next;
00388 alloc_metrics(c, f);
00389 }
00390 f->next = head;
00391 head->prev = f;
00392 return head;
00393 }
00394
00395 static void check_field_queue(struct pullup_context *c)
00396 {
00397 if (c->head->next == c->first) {
00398 struct pullup_field *f = calloc(1, sizeof(struct pullup_field));
00399 alloc_metrics(c, f);
00400 f->prev = c->head;
00401 f->next = c->first;
00402 c->head->next = f;
00403 c->first->prev = f;
00404 }
00405 }
00406
00407 void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity)
00408 {
00409 struct pullup_field *f;
00410
00411
00412 check_field_queue(c);
00413
00414
00415 if (c->last && c->last->parity == parity) return;
00416
00417 f = c->head;
00418 f->parity = parity;
00419 f->buffer = pullup_lock_buffer(b, parity);
00420 f->flags = 0;
00421 f->breaks = 0;
00422 f->affinity = 0;
00423
00424 compute_metric(c, f, parity, f->prev->prev, parity, c->diff, f->diffs);
00425 compute_metric(c, parity?f->prev:f, 0, parity?f:f->prev, 1, c->comb, f->comb);
00426 compute_metric(c, f, parity, f, -1, c->var, f->var);
00427
00428
00429 if (!c->first) c->first = c->head;
00430 c->last = c->head;
00431 c->head = c->head->next;
00432 }
00433
00434 void pullup_flush_fields(struct pullup_context *c)
00435 {
00436 struct pullup_field *f;
00437
00438 for (f = c->first; f && f != c->head; f = f->next) {
00439 pullup_release_buffer(f->buffer, f->parity);
00440 f->buffer = 0;
00441 }
00442 c->first = c->last = 0;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452 #define F_HAVE_BREAKS 1
00453 #define F_HAVE_AFFINITY 2
00454
00455
00456 #define BREAK_LEFT 1
00457 #define BREAK_RIGHT 2
00458
00459
00460
00461
00462 static int queue_length(struct pullup_field *begin, struct pullup_field *end)
00463 {
00464 int count = 1;
00465 struct pullup_field *f;
00466
00467 if (!begin || !end) return 0;
00468 for (f = begin; f != end; f = f->next) count++;
00469 return count;
00470 }
00471
00472 static int find_first_break(struct pullup_field *f, int max)
00473 {
00474 int i;
00475 for (i = 0; i < max; i++) {
00476 if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT)
00477 return i+1;
00478 f = f->next;
00479 }
00480 return 0;
00481 }
00482
00483 static void compute_breaks(struct pullup_context *c, struct pullup_field *f0)
00484 {
00485 int i;
00486 struct pullup_field *f1 = f0->next;
00487 struct pullup_field *f2 = f1->next;
00488 struct pullup_field *f3 = f2->next;
00489 int l, max_l=0, max_r=0;
00490
00491
00492
00493 if (f0->flags & F_HAVE_BREAKS) return;
00494
00495 f0->flags |= F_HAVE_BREAKS;
00496
00497
00498 if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) {
00499 f2->breaks |= BREAK_RIGHT;
00500 return;
00501 }
00502 if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) {
00503 f1->breaks |= BREAK_LEFT;
00504 return;
00505 }
00506
00507 for (i = 0; i < c->metric_len; i++) {
00508 l = f2->diffs[i] - f3->diffs[i];
00509 if (l > max_l) max_l = l;
00510 if (-l > max_r) max_r = -l;
00511 }
00512
00513
00514 if (max_l + max_r < 128) return;
00515 if (max_l > 4*max_r) f1->breaks |= BREAK_LEFT;
00516 if (max_r > 4*max_l) f2->breaks |= BREAK_RIGHT;
00517 }
00518
00519 static void compute_affinity(struct pullup_context *c, struct pullup_field *f)
00520 {
00521 int i;
00522 int max_l=0, max_r=0, l;
00523 if (f->flags & F_HAVE_AFFINITY) return;
00524 f->flags |= F_HAVE_AFFINITY;
00525 if (f->buffer == f->next->next->buffer) {
00526 f->affinity = 1;
00527 f->next->affinity = 0;
00528 f->next->next->affinity = -1;
00529 f->next->flags |= F_HAVE_AFFINITY;
00530 f->next->next->flags |= F_HAVE_AFFINITY;
00531 return;
00532 }
00533 if (1) {
00534 for (i = 0; i < c->metric_len; i++) {
00535 int lv = f->prev->var[i];
00536 int rv = f->next->var[i];
00537 int v = f->var[i];
00538 int lc = f->comb[i] - (v+lv) + ABS(v-lv);
00539 int rc = f->next->comb[i] - (v+rv) + ABS(v-rv);
00540 lc = lc>0 ? lc : 0;
00541 rc = rc>0 ? rc : 0;
00542 l = lc - rc;
00543 if (l > max_l) max_l = l;
00544 if (-l > max_r) max_r = -l;
00545 }
00546 if (max_l + max_r < 64) return;
00547 if (max_r > 6*max_l) f->affinity = -1;
00548 else if (max_l > 6*max_r) f->affinity = 1;
00549 } else {
00550 for (i = 0; i < c->metric_len; i++) {
00551 l = f->comb[i] - f->next->comb[i];
00552 if (l > max_l) max_l = l;
00553 if (-l > max_r) max_r = -l;
00554 }
00555 if (max_l + max_r < 64) return;
00556 if (max_r > 2*max_l) f->affinity = -1;
00557 else if (max_l > 2*max_r) f->affinity = 1;
00558 }
00559 }
00560
00561 static void foo(struct pullup_context *c)
00562 {
00563 struct pullup_field *f = c->first;
00564 int i, n = queue_length(f, c->last);
00565 for (i = 0; i < n-1; i++) {
00566 if (i < n-3) compute_breaks(c, f);
00567 compute_affinity(c, f);
00568 f = f->next;
00569 }
00570 }
00571
00572 static int decide_frame_length(struct pullup_context *c)
00573 {
00574 struct pullup_field *f0 = c->first;
00575 struct pullup_field *f1 = f0->next;
00576 struct pullup_field *f2 = f1->next;
00577
00578 int l;
00579
00580 if (queue_length(c->first, c->last) < 4) return 0;
00581 foo(c);
00582
00583 if (f0->affinity == -1) return 1;
00584
00585 l = find_first_break(f0, 3);
00586 if (l == 1 && c->strict_breaks < 0) l = 0;
00587
00588 switch (l) {
00589 case 1:
00590 if (c->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1)
00591 return 2;
00592 else return 1;
00593 case 2:
00594
00595 if (c->strict_pairs
00596 && (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT)
00597 && (f0->affinity != 1 || f1->affinity != -1) )
00598 return 1;
00599 if (f1->affinity == 1) return 1;
00600 else return 2;
00601 case 3:
00602 if (f2->affinity == 1) return 2;
00603 else return 3;
00604 default:
00605
00606 if (f1->affinity == 1) return 1;
00607 else if (f1->affinity == -1) return 2;
00608 else if (f2->affinity == -1) {
00609 if (f0->affinity == 1) return 3;
00610 else return 1;
00611 }
00612 else return 2;
00613 }
00614 }
00615
00616
00617 static void print_aff_and_breaks(struct pullup_context *c, struct pullup_field *f)
00618 {
00619 int i;
00620 struct pullup_field *f0 = f;
00621 const char aff_l[] = "+..", aff_r[] = "..+";
00622
00623 (void) c;
00624
00625 printf("\naffinity: ");
00626 for (i = 0; i < 4; i++) {
00627 printf("%c%d%c", aff_l[1+f->affinity], i, aff_r[1+f->affinity]);
00628 f = f->next;
00629 }
00630 f = f0;
00631 printf("\nbreaks: ");
00632 for (i=0; i<4; i++) {
00633 printf("%c%d%c", f->breaks & BREAK_LEFT ? '|' : '.', i, f->breaks & BREAK_RIGHT ? '|' : '.');
00634 f = f->next;
00635 }
00636 printf("\n");
00637 }
00638
00639
00640
00641
00642
00643 struct pullup_frame *pullup_get_frame(struct pullup_context *c)
00644 {
00645 int i;
00646 struct pullup_frame *fr = c->frame;
00647 int n = decide_frame_length(c);
00648 int aff = c->first->next->affinity;
00649
00650 if (!n) return 0;
00651 if (fr->lock) return 0;
00652
00653 if (c->verbose) {
00654 print_aff_and_breaks(c, c->first);
00655 printf("duration: %d \n", n);
00656 }
00657
00658 fr->lock++;
00659 fr->length = n;
00660 fr->parity = c->first->parity;
00661 fr->buffer = 0;
00662 for (i = 0; i < n; i++) {
00663
00664 fr->ifields[i] = c->first->buffer;
00665 c->first->buffer = 0;
00666 c->first = c->first->next;
00667 }
00668
00669 if (n == 1) {
00670 fr->ofields[fr->parity] = fr->ifields[0];
00671 fr->ofields[fr->parity^1] = 0;
00672 } else if (n == 2) {
00673 fr->ofields[fr->parity] = fr->ifields[0];
00674 fr->ofields[fr->parity^1] = fr->ifields[1];
00675 } else if (n == 3) {
00676 if (aff == 0)
00677 aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
00678
00679 fr->ofields[fr->parity] = fr->ifields[1+aff];
00680 fr->ofields[fr->parity^1] = fr->ifields[1];
00681 }
00682 pullup_lock_buffer(fr->ofields[0], 0);
00683 pullup_lock_buffer(fr->ofields[1], 1);
00684
00685 if (fr->ofields[0] == fr->ofields[1]) {
00686 fr->buffer = fr->ofields[0];
00687 pullup_lock_buffer(fr->buffer, 2);
00688 return fr;
00689 }
00690 return fr;
00691 }
00692
00693 static void copy_field(struct pullup_context *c, struct pullup_buffer *dest,
00694 struct pullup_buffer *src, int parity)
00695 {
00696 int i, j;
00697 unsigned char *d, *s;
00698 for (i = 0; i < c->nplanes; i++) {
00699 s = src->planes[i] + parity*c->stride[i];
00700 d = dest->planes[i] + parity*c->stride[i];
00701 for (j = c->h[i]>>1; j; j--) {
00702 memcpy(d, s, c->stride[i]);
00703 s += c->stride[i]<<1;
00704 d += c->stride[i]<<1;
00705 }
00706 }
00707 }
00708
00709 void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr)
00710 {
00711 int i;
00712
00713 if (fr->buffer) return;
00714 if (fr->length < 2) return;
00715 for (i = 0; i < 2; i++)
00716 {
00717 if (fr->ofields[i]->lock[i^1]) continue;
00718 fr->buffer = fr->ofields[i];
00719 pullup_lock_buffer(fr->buffer, 2);
00720 copy_field(c, fr->buffer, fr->ofields[i^1], i^1);
00721 return;
00722 }
00723 fr->buffer = pullup_get_buffer(c, 2);
00724 copy_field(c, fr->buffer, fr->ofields[0], 0);
00725 copy_field(c, fr->buffer, fr->ofields[1], 1);
00726 }
00727
00728 void pullup_release_frame(struct pullup_frame *fr)
00729 {
00730 int i;
00731 for (i = 0; i < fr->length; i++)
00732 pullup_release_buffer(fr->ifields[i], fr->parity ^ (i&1));
00733 pullup_release_buffer(fr->ofields[0], 0);
00734 pullup_release_buffer(fr->ofields[1], 1);
00735 if (fr->buffer) pullup_release_buffer(fr->buffer, 2);
00736 fr->lock--;
00737 }
00738
00739
00740
00741
00742
00743
00744 struct pullup_context *pullup_alloc_context(void)
00745 {
00746 struct pullup_context *c;
00747
00748 c = calloc(1, sizeof(struct pullup_context));
00749
00750 return c;
00751 }
00752
00753 void pullup_preinit_context(struct pullup_context *c)
00754 {
00755 c->bpp = calloc(c->nplanes, sizeof(int));
00756 c->w = calloc(c->nplanes, sizeof(int));
00757 c->h = calloc(c->nplanes, sizeof(int));
00758 c->stride = calloc(c->nplanes, sizeof(int));
00759 c->background = calloc(c->nplanes, sizeof(int));
00760 }
00761
00762 void pullup_init_context(struct pullup_context *c)
00763 {
00764 int mp = c->metric_plane;
00765 if (c->nbuffers < 10) c->nbuffers = 10;
00766 c->buffers = calloc(c->nbuffers, sizeof (struct pullup_buffer));
00767
00768 c->metric_w = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3;
00769 c->metric_h = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3;
00770 c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp];
00771 c->metric_len = c->metric_w * c->metric_h;
00772
00773 c->head = make_field_queue(c, 8);
00774
00775 c->frame = calloc(1, sizeof (struct pullup_frame));
00776 c->frame->ifields = calloc(3, sizeof (struct pullup_buffer *));
00777
00778 switch(c->format) {
00779 case PULLUP_FMT_Y:
00780 c->diff = diff_y;
00781 c->comb = licomb_y;
00782 c->var = var_y;
00783 #ifdef HAVE_MMX
00784 if (c->cpu & PULLUP_CPU_MMX) {
00785 c->diff = diff_y_mmx;
00786 c->comb = licomb_y_mmx;
00787 c->var = var_y_mmx;
00788 }
00789 #endif
00790
00791 break;
00792 #if 0
00793 case PULLUP_FMT_YUY2:
00794 c->diff = diff_yuy2;
00795 break;
00796 case PULLUP_FMT_RGB32:
00797 c->diff = diff_rgb32;
00798 break;
00799 #endif
00800 }
00801 }
00802
00803 void pullup_free_context(struct pullup_context *c)
00804 {
00805 struct pullup_field *f;
00806 free(c->buffers);
00807 f = c->head;
00808 do {
00809 free(f->diffs);
00810 free(f->comb);
00811 free(f->var);
00812 f = f->next;
00813 free(f->prev);
00814 } while (f != c->head);
00815 free(c->frame->ifields);
00816 free(c->frame);
00817 free(c->stride);
00818 free(c->bpp);
00819 free(c->w);
00820 free(c->h);
00821 free(c->background);
00822 free(c);
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832