typo fixes
[mplayer/greg.git] / libmpcodecs / pullup.c
blob6f731ec826f179f1fdaa758fe1dc25ca79f5e17a
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "pullup.h"
7 #include "config.h"
11 #ifdef ARCH_X86
12 #ifdef HAVE_MMX
13 static int diff_y_mmx(unsigned char *a, unsigned char *b, int s)
15 int ret;
16 asm volatile (
17 "movl $4, %%ecx \n\t"
18 "pxor %%mm4, %%mm4 \n\t"
19 "pxor %%mm7, %%mm7 \n\t"
21 "1: \n\t"
23 "movq (%%esi), %%mm0 \n\t"
24 "movq (%%esi), %%mm2 \n\t"
25 "addl %%eax, %%esi \n\t"
26 "movq (%%edi), %%mm1 \n\t"
27 "addl %%eax, %%edi \n\t"
28 "psubusb %%mm1, %%mm2 \n\t"
29 "psubusb %%mm0, %%mm1 \n\t"
30 "movq %%mm2, %%mm0 \n\t"
31 "movq %%mm1, %%mm3 \n\t"
32 "punpcklbw %%mm7, %%mm0 \n\t"
33 "punpcklbw %%mm7, %%mm1 \n\t"
34 "punpckhbw %%mm7, %%mm2 \n\t"
35 "punpckhbw %%mm7, %%mm3 \n\t"
36 "paddw %%mm0, %%mm4 \n\t"
37 "paddw %%mm1, %%mm4 \n\t"
38 "paddw %%mm2, %%mm4 \n\t"
39 "paddw %%mm3, %%mm4 \n\t"
41 "decl %%ecx \n\t"
42 "jnz 1b \n\t"
44 "movq %%mm4, %%mm3 \n\t"
45 "punpcklwd %%mm7, %%mm4 \n\t"
46 "punpckhwd %%mm7, %%mm3 \n\t"
47 "paddd %%mm4, %%mm3 \n\t"
48 "movd %%mm3, %%eax \n\t"
49 "psrlq $32, %%mm3 \n\t"
50 "movd %%mm3, %%edx \n\t"
51 "addl %%edx, %%eax \n\t"
52 "emms \n\t"
53 : "=a" (ret)
54 : "S" (a), "D" (b), "a" (s)
55 : "%ecx", "%edx"
57 return ret;
60 static int licomb_y_mmx(unsigned char *a, unsigned char *b, int s)
62 int ret;
63 asm volatile (
64 "movl $4, %%ecx \n\t"
65 "pxor %%mm6, %%mm6 \n\t"
66 "pxor %%mm7, %%mm7 \n\t"
67 "subl %%eax, %%edi \n\t"
69 "2: \n\t"
71 "movq (%%esi), %%mm0 \n\t"
72 "movq (%%edi), %%mm1 \n\t"
73 "punpcklbw %%mm7, %%mm0 \n\t"
74 "movq (%%edi,%%eax), %%mm2 \n\t"
75 "punpcklbw %%mm7, %%mm1 \n\t"
76 "punpcklbw %%mm7, %%mm2 \n\t"
77 "paddw %%mm0, %%mm0 \n\t"
78 "paddw %%mm2, %%mm1 \n\t"
79 "movq %%mm0, %%mm2 \n\t"
80 "psubusw %%mm1, %%mm0 \n\t"
81 "psubusw %%mm2, %%mm1 \n\t"
82 "paddw %%mm0, %%mm6 \n\t"
83 "paddw %%mm1, %%mm6 \n\t"
85 "movq (%%esi), %%mm0 \n\t"
86 "movq (%%edi), %%mm1 \n\t"
87 "punpckhbw %%mm7, %%mm0 \n\t"
88 "movq (%%edi,%%eax), %%mm2 \n\t"
89 "punpckhbw %%mm7, %%mm1 \n\t"
90 "punpckhbw %%mm7, %%mm2 \n\t"
91 "paddw %%mm0, %%mm0 \n\t"
92 "paddw %%mm2, %%mm1 \n\t"
93 "movq %%mm0, %%mm2 \n\t"
94 "psubusw %%mm1, %%mm0 \n\t"
95 "psubusw %%mm2, %%mm1 \n\t"
96 "paddw %%mm0, %%mm6 \n\t"
97 "paddw %%mm1, %%mm6 \n\t"
99 "movq (%%edi,%%eax), %%mm0 \n\t"
100 "movq (%%esi), %%mm1 \n\t"
101 "punpcklbw %%mm7, %%mm0 \n\t"
102 "movq (%%esi,%%eax), %%mm2 \n\t"
103 "punpcklbw %%mm7, %%mm1 \n\t"
104 "punpcklbw %%mm7, %%mm2 \n\t"
105 "paddw %%mm0, %%mm0 \n\t"
106 "paddw %%mm2, %%mm1 \n\t"
107 "movq %%mm0, %%mm2 \n\t"
108 "psubusw %%mm1, %%mm0 \n\t"
109 "psubusw %%mm2, %%mm1 \n\t"
110 "paddw %%mm0, %%mm6 \n\t"
111 "paddw %%mm1, %%mm6 \n\t"
113 "movq (%%edi,%%eax), %%mm0 \n\t"
114 "movq (%%esi), %%mm1 \n\t"
115 "punpckhbw %%mm7, %%mm0 \n\t"
116 "movq (%%esi,%%eax), %%mm2 \n\t"
117 "punpckhbw %%mm7, %%mm1 \n\t"
118 "punpckhbw %%mm7, %%mm2 \n\t"
119 "paddw %%mm0, %%mm0 \n\t"
120 "paddw %%mm2, %%mm1 \n\t"
121 "movq %%mm0, %%mm2 \n\t"
122 "psubusw %%mm1, %%mm0 \n\t"
123 "psubusw %%mm2, %%mm1 \n\t"
124 "paddw %%mm0, %%mm6 \n\t"
125 "paddw %%mm1, %%mm6 \n\t"
127 "addl %%eax, %%esi \n\t"
128 "addl %%eax, %%edi \n\t"
129 "decl %%ecx \n\t"
130 "jnz 2b \n\t"
132 "movq %%mm6, %%mm5 \n\t"
133 "punpcklwd %%mm7, %%mm6 \n\t"
134 "punpckhwd %%mm7, %%mm5 \n\t"
135 "paddd %%mm6, %%mm5 \n\t"
136 "movd %%mm5, %%eax \n\t"
137 "psrlq $32, %%mm5 \n\t"
138 "movd %%mm5, %%edx \n\t"
139 "addl %%edx, %%eax \n\t"
141 "emms \n\t"
142 : "=a" (ret)
143 : "S" (a), "D" (b), "a" (s)
144 : "%ecx", "%edx"
146 return ret;
149 static int var_y_mmx(unsigned char *a, unsigned char *b, int s)
151 int ret;
152 asm volatile (
153 "movl $3, %%ecx \n\t"
154 "pxor %%mm4, %%mm4 \n\t"
155 "pxor %%mm7, %%mm7 \n\t"
157 "1: \n\t"
159 "movq (%%esi), %%mm0 \n\t"
160 "movq (%%esi), %%mm2 \n\t"
161 "movq (%%esi,%%eax), %%mm1 \n\t"
162 "addl %%eax, %%esi \n\t"
163 "psubusb %%mm1, %%mm2 \n\t"
164 "psubusb %%mm0, %%mm1 \n\t"
165 "movq %%mm2, %%mm0 \n\t"
166 "movq %%mm1, %%mm3 \n\t"
167 "punpcklbw %%mm7, %%mm0 \n\t"
168 "punpcklbw %%mm7, %%mm1 \n\t"
169 "punpckhbw %%mm7, %%mm2 \n\t"
170 "punpckhbw %%mm7, %%mm3 \n\t"
171 "paddw %%mm0, %%mm4 \n\t"
172 "paddw %%mm1, %%mm4 \n\t"
173 "paddw %%mm2, %%mm4 \n\t"
174 "paddw %%mm3, %%mm4 \n\t"
176 "decl %%ecx \n\t"
177 "jnz 1b \n\t"
179 "movq %%mm4, %%mm3 \n\t"
180 "punpcklwd %%mm7, %%mm4 \n\t"
181 "punpckhwd %%mm7, %%mm3 \n\t"
182 "paddd %%mm4, %%mm3 \n\t"
183 "movd %%mm3, %%eax \n\t"
184 "psrlq $32, %%mm3 \n\t"
185 "movd %%mm3, %%edx \n\t"
186 "addl %%edx, %%eax \n\t"
187 "emms \n\t"
188 : "=a" (ret)
189 : "S" (a), "a" (s)
190 : "%ecx", "%edx"
192 return 4*ret;
194 #endif
195 #endif
197 #define ABS(a) (((a)^((a)>>31))-((a)>>31))
199 static int diff_y(unsigned char *a, unsigned char *b, int s)
201 int i, j, diff=0;
202 for (i=4; i; i--) {
203 for (j=0; j<8; j++) diff += ABS(a[j]-b[j]);
204 a+=s; b+=s;
206 return diff;
209 static int licomb_y(unsigned char *a, unsigned char *b, int s)
211 int i, j, diff=0;
212 for (i=4; i; i--) {
213 for (j=0; j<8; j++)
214 diff += ABS((a[j]<<1) - b[j-s] - b[j])
215 + ABS((b[j]<<1) - a[j] - a[j+s]);
216 a+=s; b+=s;
218 return diff;
221 static int qpcomb_y(unsigned char *a, unsigned char *b, int s)
223 int i, j, diff=0;
224 for (i=4; i; i--) {
225 for (j=0; j<8; j++)
226 diff += ABS(a[j] - 3*b[j-s] + 3*a[j+s] - b[j]);
227 a+=s; b+=s;
229 return diff;
232 #if 0
233 static int licomb_y_test(unsigned char *a, unsigned char *b, int s)
235 int c = licomb_y(a,b,s);
236 int m = licomb_y_mmx(a,b,s);
237 if (c != m) printf("%d != %d\n", c, m);
238 return m;
240 #endif
242 static int var_y(unsigned char *a, unsigned char *b, int s)
244 int i, j, var=0;
245 for (i=3; i; i--) {
246 for (j=0; j<8; j++) {
247 var += ABS(a[j]-a[j+s]);
249 a+=s; b+=s;
251 return 4*var; /* match comb scaling */
262 static void alloc_buffer(struct pullup_context *c, struct pullup_buffer *b)
264 int i;
265 if (b->planes) return;
266 b->planes = calloc(c->nplanes, sizeof(unsigned char *));
267 for (i = 0; i < c->nplanes; i++) {
268 b->planes[i] = malloc(c->h[i]*c->stride[i]);
269 /* Deal with idiotic 128=0 for chroma: */
270 memset(b->planes[i], c->background[i], c->h[i]*c->stride[i]);
274 struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity)
276 if (!b) return 0;
277 if ((parity+1) & 1) b->lock[0]++;
278 if ((parity+1) & 2) b->lock[1]++;
279 return b;
282 void pullup_release_buffer(struct pullup_buffer *b, int parity)
284 if (!b) return;
285 if ((parity+1) & 1) b->lock[0]--;
286 if ((parity+1) & 2) b->lock[1]--;
289 struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity)
291 int i;
293 /* Try first to get the sister buffer for the previous field */
294 if (parity < 2 && c->last && parity != c->last->parity
295 && !c->last->buffer->lock[parity]) {
296 alloc_buffer(c, c->last->buffer);
297 return pullup_lock_buffer(c->last->buffer, parity);
300 /* Prefer a buffer with both fields open */
301 for (i = 0; i < c->nbuffers; i++) {
302 if (c->buffers[i].lock[0]) continue;
303 if (c->buffers[i].lock[1]) continue;
304 alloc_buffer(c, &c->buffers[i]);
305 return pullup_lock_buffer(&c->buffers[i], parity);
308 if (parity == 2) return 0;
310 /* Search for any half-free buffer */
311 for (i = 0; i < c->nbuffers; i++) {
312 if (((parity+1) & 1) && c->buffers[i].lock[0]) continue;
313 if (((parity+1) & 2) && c->buffers[i].lock[1]) continue;
314 alloc_buffer(c, &c->buffers[i]);
315 return pullup_lock_buffer(&c->buffers[i], parity);
318 return 0;
326 static void compute_metric(struct pullup_context *c,
327 struct pullup_field *fa, int pa,
328 struct pullup_field *fb, int pb,
329 int (*func)(unsigned char *, unsigned char *, int), int *dest)
331 unsigned char *a, *b;
332 int x, y;
333 int mp = c->metric_plane;
334 int xstep = c->bpp[mp];
335 int ystep = c->stride[mp]<<3;
336 int s = c->stride[mp]<<1; /* field stride */
337 int w = c->metric_w*xstep;
339 if (!fa->buffer || !fb->buffer) return;
341 /* Shortcut for duplicate fields (e.g. from RFF flag) */
342 if (fa->buffer == fb->buffer && pa == pb) {
343 memset(dest, 0, c->metric_len * sizeof(int));
344 return;
347 a = fa->buffer->planes[mp] + pa * c->stride[mp] + c->metric_offset;
348 b = fb->buffer->planes[mp] + pb * c->stride[mp] + c->metric_offset;
350 for (y = c->metric_h; y; y--) {
351 for (x = 0; x < w; x += xstep) {
352 *dest++ = func(a + x, b + x, s);
354 a += ystep; b += ystep;
362 static void alloc_metrics(struct pullup_context *c, struct pullup_field *f)
364 f->diffs = calloc(c->metric_len, sizeof(int));
365 f->comb = calloc(c->metric_len, sizeof(int));
366 f->var = calloc(c->metric_len, sizeof(int));
367 /* add more metrics here as needed */
370 static struct pullup_field *make_field_queue(struct pullup_context *c, int len)
372 struct pullup_field *head, *f;
373 f = head = calloc(1, sizeof(struct pullup_field));
374 alloc_metrics(c, f);
375 for (; len > 0; len--) {
376 f->next = calloc(1, sizeof(struct pullup_field));
377 f->next->prev = f;
378 f = f->next;
379 alloc_metrics(c, f);
381 f->next = head;
382 head->prev = f;
383 return head;
386 static void check_field_queue(struct pullup_context *c)
388 if (c->head->next == c->first) {
389 struct pullup_field *f = calloc(1, sizeof(struct pullup_field));
390 alloc_metrics(c, f);
391 f->prev = c->head;
392 f->next = c->first;
393 c->head->next = f;
394 c->first->prev = f;
398 void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity)
400 struct pullup_field *f;
402 /* Grow the circular list if needed */
403 check_field_queue(c);
405 /* Cannot have two fields of same parity in a row; drop the new one */
406 if (c->last && c->last->parity == parity) return;
408 f = c->head;
409 f->parity = parity;
410 f->buffer = pullup_lock_buffer(b, parity);
411 f->flags = 0;
412 f->breaks = 0;
413 f->affinity = 0;
415 compute_metric(c, f, parity, f->prev->prev, parity, c->diff, f->diffs);
416 compute_metric(c, parity?f->prev:f, 0, parity?f:f->prev, 1, c->comb, f->comb);
417 compute_metric(c, f, parity, f, -1, c->var, f->var);
419 /* Advance the circular list */
420 if (!c->first) c->first = c->head;
421 c->last = c->head;
422 c->head = c->head->next;
425 void pullup_flush_fields(struct pullup_context *c)
427 struct pullup_field *f;
429 for (f = c->first; f && f != c->head; f = f->next) {
430 pullup_release_buffer(f->buffer, f->parity);
431 f->buffer = 0;
433 c->first = c->last = 0;
443 #define F_HAVE_BREAKS 1
444 #define F_HAVE_AFFINITY 2
447 #define BREAK_LEFT 1
448 #define BREAK_RIGHT 2
453 static int queue_length(struct pullup_field *begin, struct pullup_field *end)
455 int count = 1;
456 struct pullup_field *f;
458 if (!begin || !end) return 0;
459 for (f = begin; f != end; f = f->next) count++;
460 return count;
463 static int find_first_break(struct pullup_field *f, int max)
465 int i;
466 for (i = 0; i < max; i++) {
467 if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT)
468 return i+1;
469 f = f->next;
471 return 0;
474 static void compute_breaks(struct pullup_context *c, struct pullup_field *f0)
476 int i;
477 struct pullup_field *f1 = f0->next;
478 struct pullup_field *f2 = f1->next;
479 struct pullup_field *f3 = f2->next;
480 int l, max_l=0, max_r=0;
481 //struct pullup_field *ff;
482 //for (i=0, ff=c->first; ff != f0; i++, ff=ff->next);
484 if (f0->flags & F_HAVE_BREAKS) return;
485 //printf("\n%d: ", i);
486 f0->flags |= F_HAVE_BREAKS;
488 /* Special case when fields are 100% identical */
489 if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) {
490 f2->breaks |= BREAK_RIGHT;
491 return;
493 if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) {
494 f1->breaks |= BREAK_LEFT;
495 return;
498 for (i = 0; i < c->metric_len; i++) {
499 l = f2->diffs[i] - f3->diffs[i];
500 if (l > max_l) max_l = l;
501 if (-l > max_r) max_r = -l;
503 /* Don't get tripped up when differences are mostly quant error */
504 //printf("%d %d\n", max_l, max_r);
505 if (max_l + max_r < 128) return;
506 if (max_l > 4*max_r) f1->breaks |= BREAK_LEFT;
507 if (max_r > 4*max_l) f2->breaks |= BREAK_RIGHT;
510 static void compute_affinity(struct pullup_context *c, struct pullup_field *f)
512 int i;
513 int max_l=0, max_r=0, l;
514 if (f->flags & F_HAVE_AFFINITY) return;
515 f->flags |= F_HAVE_AFFINITY;
516 if (f->buffer == f->next->next->buffer) {
517 f->affinity = 1;
518 f->next->affinity = 0;
519 f->next->next->affinity = -1;
520 f->next->flags |= F_HAVE_AFFINITY;
521 f->next->next->flags |= F_HAVE_AFFINITY;
522 return;
524 if (1) {
525 for (i = 0; i < c->metric_len; i++) {
526 int lv = f->prev->var[i];
527 int rv = f->next->var[i];
528 int v = f->var[i];
529 int lc = f->comb[i] - (v+lv) + ABS(v-lv);
530 int rc = f->next->comb[i] - (v+rv) + ABS(v-rv);
531 lc = lc>0 ? lc : 0;
532 rc = rc>0 ? rc : 0;
533 l = lc - rc;
534 if (l > max_l) max_l = l;
535 if (-l > max_r) max_r = -l;
537 if (max_l + max_r < 64) return;
538 if (max_r > 6*max_l) f->affinity = -1;
539 else if (max_l > 6*max_r) f->affinity = 1;
540 } else {
541 for (i = 0; i < c->metric_len; i++) {
542 l = f->comb[i] - f->next->comb[i];
543 if (l > max_l) max_l = l;
544 if (-l > max_r) max_r = -l;
546 if (max_l + max_r < 64) return;
547 if (max_r > 2*max_l) f->affinity = -1;
548 else if (max_l > 2*max_r) f->affinity = 1;
552 static void foo(struct pullup_context *c)
554 struct pullup_field *f = c->first;
555 int i, n = queue_length(f, c->last);
556 for (i = 0; i < n-1; i++) {
557 if (i < n-3) compute_breaks(c, f);
558 compute_affinity(c, f);
559 f = f->next;
563 static int decide_frame_length(struct pullup_context *c)
565 struct pullup_field *f0 = c->first;
566 struct pullup_field *f1 = f0->next;
567 struct pullup_field *f2 = f1->next;
568 struct pullup_field *f3 = f2->next;
569 int l;
571 if (queue_length(c->first, c->last) < 4) return 0;
572 foo(c);
574 if (f0->affinity == -1) return 1;
576 l = find_first_break(f0, 3);
577 if (l == 1 && c->strict_breaks < 0) l = 0;
579 switch (l) {
580 case 1:
581 if (c->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1)
582 return 2;
583 else return 1;
584 case 2:
585 /* FIXME: strictly speaking, f0->prev is no longer valid... :) */
586 if (c->strict_pairs
587 && (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT)
588 && (f0->affinity != 1 || f1->affinity != -1) )
589 return 1;
590 if (f1->affinity == 1) return 1;
591 else return 2;
592 case 3:
593 if (f2->affinity == 1) return 2;
594 else return 3;
595 default:
596 /* 9 possibilities covered before switch */
597 if (f1->affinity == 1) return 1; /* covers 6 */
598 else if (f1->affinity == -1) return 2; /* covers 6 */
599 else if (f2->affinity == -1) { /* covers 2 */
600 if (f0->affinity == 1) return 3;
601 else return 1;
603 else return 2; /* the remaining 6 */
608 static void print_aff_and_breaks(struct pullup_context *c, struct pullup_field *f)
610 int i;
611 int max_l, max_r, l;
612 struct pullup_field *f0 = f;
613 const char aff_l[] = "+..", aff_r[] = "..+";
614 printf("\naffinity: ");
615 for (i = 0; i < 4; i++) {
616 printf("%c%d%c", aff_l[1+f->affinity], i, aff_r[1+f->affinity]);
617 f = f->next;
619 f = f0;
620 printf("\nbreaks: ");
621 for (i=0; i<4; i++) {
622 printf("%c%d%c", f->breaks & BREAK_LEFT ? '|' : '.', i, f->breaks & BREAK_RIGHT ? '|' : '.');
623 f = f->next;
625 printf("\n");
632 struct pullup_frame *pullup_get_frame(struct pullup_context *c)
634 int i;
635 struct pullup_frame *fr = c->frame;
636 int n = decide_frame_length(c);
637 int aff = c->first->next->affinity;
639 if (!n) return 0;
640 if (fr->lock) return 0;
642 if (c->verbose) {
643 print_aff_and_breaks(c, c->first);
644 printf("duration: %d \n", n);
647 fr->lock++;
648 fr->length = n;
649 fr->parity = c->first->parity;
650 fr->buffer = 0;
651 for (i = 0; i < n; i++) {
652 /* We cheat and steal the buffer without release+relock */
653 fr->ifields[i] = c->first->buffer;
654 c->first->buffer = 0;
655 c->first = c->first->next;
658 if (n == 1) {
659 fr->ofields[fr->parity] = fr->ifields[0];
660 fr->ofields[fr->parity^1] = 0;
661 } else if (n == 2) {
662 fr->ofields[fr->parity] = fr->ifields[0];
663 fr->ofields[fr->parity^1] = fr->ifields[1];
664 } else if (n == 3) {
665 if (aff == 0)
666 aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
667 /* else if (c->verbose) printf("forced aff: %d \n", aff); */
668 fr->ofields[fr->parity] = fr->ifields[1+aff];
669 fr->ofields[fr->parity^1] = fr->ifields[1];
671 pullup_lock_buffer(fr->ofields[0], 0);
672 pullup_lock_buffer(fr->ofields[1], 1);
674 if (fr->ofields[0] == fr->ofields[1]) {
675 fr->buffer = fr->ofields[0];
676 pullup_lock_buffer(fr->buffer, 2);
677 return fr;
679 return fr;
682 static void copy_field(struct pullup_context *c, struct pullup_buffer *dest,
683 struct pullup_buffer *src, int parity)
685 int i, j;
686 unsigned char *d, *s;
687 for (i = 0; i < c->nplanes; i++) {
688 s = src->planes[i] + parity*c->stride[i];
689 d = dest->planes[i] + parity*c->stride[i];
690 for (j = c->h[i]>>1; j; j--) {
691 memcpy(d, s, c->stride[i]);
692 s += c->stride[i]<<1;
693 d += c->stride[i]<<1;
698 void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr)
700 int i;
701 int par = fr->parity;
702 if (fr->buffer) return;
703 if (fr->length < 2) return; /* FIXME: deal with this */
704 for (i = 0; i < 2; i++)
706 if (fr->ofields[i]->lock[i^1]) continue;
707 fr->buffer = fr->ofields[i];
708 pullup_lock_buffer(fr->buffer, 2);
709 copy_field(c, fr->buffer, fr->ofields[i^1], i^1);
710 return;
712 fr->buffer = pullup_get_buffer(c, 2);
713 copy_field(c, fr->buffer, fr->ofields[0], 0);
714 copy_field(c, fr->buffer, fr->ofields[1], 1);
717 void pullup_release_frame(struct pullup_frame *fr)
719 int i;
720 for (i = 0; i < fr->length; i++)
721 pullup_release_buffer(fr->ifields[i], fr->parity ^ (i&1));
722 pullup_release_buffer(fr->ofields[0], 0);
723 pullup_release_buffer(fr->ofields[1], 1);
724 if (fr->buffer) pullup_release_buffer(fr->buffer, 2);
725 fr->lock--;
733 struct pullup_context *pullup_alloc_context(void)
735 struct pullup_context *c;
737 c = calloc(1, sizeof(struct pullup_context));
739 return c;
742 void pullup_preinit_context(struct pullup_context *c)
744 c->bpp = calloc(c->nplanes, sizeof(int));
745 c->w = calloc(c->nplanes, sizeof(int));
746 c->h = calloc(c->nplanes, sizeof(int));
747 c->stride = calloc(c->nplanes, sizeof(int));
748 c->background = calloc(c->nplanes, sizeof(int));
751 void pullup_init_context(struct pullup_context *c)
753 int mp = c->metric_plane;
754 if (c->nbuffers < 10) c->nbuffers = 10;
755 c->buffers = calloc(c->nbuffers, sizeof (struct pullup_buffer));
757 c->metric_w = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3;
758 c->metric_h = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3;
759 c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp];
760 c->metric_len = c->metric_w * c->metric_h;
762 c->head = make_field_queue(c, 8);
764 c->frame = calloc(1, sizeof (struct pullup_frame));
765 c->frame->ifields = calloc(3, sizeof (struct pullup_buffer *));
767 switch(c->format) {
768 case PULLUP_FMT_Y:
769 c->diff = diff_y;
770 c->comb = licomb_y;
771 c->var = var_y;
772 #ifdef ARCH_X86
773 #ifdef HAVE_MMX
774 if (c->cpu & PULLUP_CPU_MMX) {
775 c->diff = diff_y_mmx;
776 c->comb = licomb_y_mmx;
777 c->var = var_y_mmx;
779 #endif
780 #endif
781 /* c->comb = qpcomb_y; */
782 break;
783 #if 0
784 case PULLUP_FMT_YUY2:
785 c->diff = diff_yuy2;
786 break;
787 case PULLUP_FMT_RGB32:
788 c->diff = diff_rgb32;
789 break;
790 #endif
794 void pullup_free_context(struct pullup_context *c)
796 struct pullup_field *f;
797 free(c->buffers);
798 f = c->head;
799 do {
800 free(f->diffs);
801 free(f->comb);
802 f = f->next;
803 free(f->prev);
804 } while (f != c->head);
805 free(c->frame);
806 free(c);