|
MythTV
0.26-pre
|
00001 /* 00002 * Copyright (C) MPlayer Project license GPL v2 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 #if 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)); /* <- to suppress compiler warning */ 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; /* match comb scaling */ 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 /* Deal with idiotic 128=0 for chroma: */ 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 /* Try first to get the sister buffer for the previous field */ 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 /* Prefer a buffer with both fields open */ 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 /* Search for any half-free buffer */ 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; /* field stride */ 00346 int w = c->metric_w*xstep; 00347 00348 if (!fa->buffer || !fb->buffer) return; 00349 00350 /* Shortcut for duplicate fields (e.g. from RFF flag) */ 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 /* add more metrics here as needed */ 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 /* Grow the circular list if needed */ 00412 check_field_queue(c); 00413 00414 /* Cannot have two fields of same parity in a row; drop the new one */ 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 /* Advance the circular list */ 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 //struct pullup_field *ff; 00491 //for (i=0, ff=c->first; ff != f0; i++, ff=ff->next); 00492 00493 if (f0->flags & F_HAVE_BREAKS) return; 00494 //printf("\n%d: ", i); 00495 f0->flags |= F_HAVE_BREAKS; 00496 00497 /* Special case when fields are 100% identical */ 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 /* Don't get tripped up when differences are mostly quant error */ 00513 //printf("%d %d\n", max_l, max_r); 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 /*struct pullup_field *f3 = f2->next;*/ 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 /* FIXME: strictly speaking, f0->prev is no longer valid... :) */ 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 /* 9 possibilities covered before switch */ 00606 if (f1->affinity == 1) return 1; /* covers 6 */ 00607 else if (f1->affinity == -1) return 2; /* covers 6 */ 00608 else if (f2->affinity == -1) { /* covers 2 */ 00609 if (f0->affinity == 1) return 3; 00610 else return 1; 00611 } 00612 else return 2; /* the remaining 6 */ 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 /* We cheat and steal the buffer without release+relock */ 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 /* else if (c->verbose) printf("forced aff: %d \n", aff); */ 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 /*int par = fr->parity;*/ 00713 if (fr->buffer) return; 00714 if (fr->length < 2) return; /* FIXME: deal with this */ 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 if (!fr->buffer) return; 00725 copy_field(c, fr->buffer, fr->ofields[0], 0); 00726 copy_field(c, fr->buffer, fr->ofields[1], 1); 00727 } 00728 00729 void pullup_release_frame(struct pullup_frame *fr) 00730 { 00731 int i; 00732 for (i = 0; i < fr->length; i++) 00733 pullup_release_buffer(fr->ifields[i], fr->parity ^ (i&1)); 00734 pullup_release_buffer(fr->ofields[0], 0); 00735 pullup_release_buffer(fr->ofields[1], 1); 00736 if (fr->buffer) pullup_release_buffer(fr->buffer, 2); 00737 fr->lock--; 00738 } 00739 00740 00741 00742 00743 00744 00745 struct pullup_context *pullup_alloc_context(void) 00746 { 00747 struct pullup_context *c; 00748 00749 c = calloc(1, sizeof(struct pullup_context)); 00750 00751 return c; 00752 } 00753 00754 void pullup_preinit_context(struct pullup_context *c) 00755 { 00756 c->bpp = calloc(c->nplanes, sizeof(int)); 00757 c->w = calloc(c->nplanes, sizeof(int)); 00758 c->h = calloc(c->nplanes, sizeof(int)); 00759 c->stride = calloc(c->nplanes, sizeof(int)); 00760 c->background = calloc(c->nplanes, sizeof(int)); 00761 } 00762 00763 void pullup_init_context(struct pullup_context *c) 00764 { 00765 int mp = c->metric_plane; 00766 if (c->nbuffers < 10) c->nbuffers = 10; 00767 c->buffers = calloc(c->nbuffers, sizeof (struct pullup_buffer)); 00768 00769 c->metric_w = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3; 00770 c->metric_h = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3; 00771 c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp]; 00772 c->metric_len = c->metric_w * c->metric_h; 00773 00774 c->head = make_field_queue(c, 8); 00775 00776 c->frame = calloc(1, sizeof (struct pullup_frame)); 00777 c->frame->ifields = calloc(3, sizeof (struct pullup_buffer *)); 00778 00779 switch(c->format) { 00780 case PULLUP_FMT_Y: 00781 c->diff = diff_y; 00782 c->comb = licomb_y; 00783 c->var = var_y; 00784 #if HAVE_MMX 00785 if (c->cpu & PULLUP_CPU_MMX) { 00786 c->diff = diff_y_mmx; 00787 c->comb = licomb_y_mmx; 00788 c->var = var_y_mmx; 00789 } 00790 #endif 00791 /* c->comb = qpcomb_y; */ 00792 break; 00793 #if 0 00794 case PULLUP_FMT_YUY2: 00795 c->diff = diff_yuy2; 00796 break; 00797 case PULLUP_FMT_RGB32: 00798 c->diff = diff_rgb32; 00799 break; 00800 #endif 00801 } 00802 } 00803 00804 void pullup_free_context(struct pullup_context *c) 00805 { 00806 struct pullup_field *f; 00807 free(c->buffers); 00808 f = c->head; 00809 do { 00810 free(f->diffs); 00811 free(f->comb); 00812 free(f->var); 00813 f = f->next; 00814 free(f->prev); 00815 } while (f != c->head); 00816 free(c->frame->ifields); 00817 free(c->frame); 00818 free(c->stride); 00819 free(c->bpp); 00820 free(c->w); 00821 free(c->h); 00822 free(c->background); 00823 free(c); 00824 } 00825 00826 00827 00828 00829 00830 00831 00832 00833
1.7.6.1