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