📄 pullup.c
字号:
for (f = c->first; f && f != c->head; f = f->next) { pullup_release_buffer(f->buffer, f->parity); f->buffer = 0; } c->first = c->last = 0;}#define F_HAVE_BREAKS 1#define F_HAVE_AFFINITY 2#define BREAK_LEFT 1#define BREAK_RIGHT 2static int queue_length(struct pullup_field *begin, struct pullup_field *end){ int count = 1; struct pullup_field *f; if (!begin || !end) return 0; for (f = begin; f != end; f = f->next) count++; return count;}static int find_first_break(struct pullup_field *f, int max){ int i; for (i = 0; i < max; i++) { if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT) return i+1; f = f->next; } return 0;}static void compute_breaks(struct pullup_context *c, struct pullup_field *f0){ int i; struct pullup_field *f1 = f0->next; struct pullup_field *f2 = f1->next; struct pullup_field *f3 = f2->next; int l, max_l=0, max_r=0; //struct pullup_field *ff; //for (i=0, ff=c->first; ff != f0; i++, ff=ff->next); if (f0->flags & F_HAVE_BREAKS) return; //printf("\n%d: ", i); f0->flags |= F_HAVE_BREAKS; /* Special case when fields are 100% identical */ if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) { f2->breaks |= BREAK_RIGHT; return; } if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) { f1->breaks |= BREAK_LEFT; return; } for (i = 0; i < c->metric_len; i++) { l = f2->diffs[i] - f3->diffs[i]; if (l > max_l) max_l = l; if (-l > max_r) max_r = -l; } /* Don't get tripped up when differences are mostly quant error */ //printf("%d %d\n", max_l, max_r); if (max_l + max_r < 128) return; if (max_l > 4*max_r) f1->breaks |= BREAK_LEFT; if (max_r > 4*max_l) f2->breaks |= BREAK_RIGHT;}static void compute_affinity(struct pullup_context *c, struct pullup_field *f){ int i; int max_l=0, max_r=0, l; if (f->flags & F_HAVE_AFFINITY) return; f->flags |= F_HAVE_AFFINITY; if (f->buffer == f->next->next->buffer) { f->affinity = 1; f->next->affinity = 0; f->next->next->affinity = -1; f->next->flags |= F_HAVE_AFFINITY; f->next->next->flags |= F_HAVE_AFFINITY; return; } for (i = 0; i < c->metric_len; i++) { l = f->comb[i] - f->next->comb[i]; if (l > max_l) max_l = l; if (-l > max_r) max_r = -l; } if (max_l + max_r < 64) return; if (max_r > 2*max_l) f->affinity = -1; else if (max_l > 2*max_r) f->affinity = 1;}static void foo(struct pullup_context *c){ struct pullup_field *f = c->first; int i, n = queue_length(f, c->last); for (i = 0; i < n-1; i++) { if (i < n-3) compute_breaks(c, f); compute_affinity(c, f); f = f->next; }}static int decide_frame_length(struct pullup_context *c){ struct pullup_field *f0 = c->first; struct pullup_field *f1 = f0->next; struct pullup_field *f2 = f1->next; struct pullup_field *f3 = f2->next; int l; if (queue_length(c->first, c->last) < 4) return 0; foo(c); if (f0->affinity == -1) return 1; l = find_first_break(f0, 3); if (l == 1 && c->strict_breaks < 0) l = 0; switch (l) { case 1: if (c->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1) return 2; else return 1; case 2: /* FIXME: strictly speaking, f0->prev is no longer valid... :) */ if (c->strict_pairs && (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT) && (f0->affinity != 1 || f1->affinity != -1) ) return 1; if (f1->affinity == 1) return 1; else return 2; case 3: if (f2->affinity == 1) return 2; else return 3; default: /* 9 possibilities covered before switch */ if (f1->affinity == 1) return 1; /* covers 6 */ else if (f1->affinity == -1) return 2; /* covers 6 */ else if (f2->affinity == -1) { /* covers 2 */ if (f0->affinity == 1) return 3; else return 1; } else return 2; /* the remaining 6 */ }}static void print_aff_and_breaks(struct pullup_context *c, struct pullup_field *f){ int i; int max_l, max_r, l; struct pullup_field *f0 = f; const char aff_l[] = "+..", aff_r[] = "..+"; printf("\naffinity: "); for (i = 0; i < 4; i++) { printf("%c%d%c", aff_l[1+f->affinity], i, aff_r[1+f->affinity]); f = f->next; } f = f0; printf("\nbreaks: "); for (i=0; i<4; i++) { printf("%c%d%c", f->breaks & BREAK_LEFT ? '|' : '.', i, f->breaks & BREAK_RIGHT ? '|' : '.'); f = f->next; } printf("\n");}struct pullup_frame *pullup_get_frame(struct pullup_context *c){ int i; struct pullup_frame *fr = c->frame; int n = decide_frame_length(c); int aff = c->first->next->affinity; if (!n) return 0; if (fr->lock) return 0; if (c->verbose) { print_aff_and_breaks(c, c->first); printf("duration: %d \n", n); } fr->lock++; fr->length = n; fr->parity = c->first->parity; fr->buffer = 0; for (i = 0; i < n; i++) { /* We cheat and steal the buffer without release+relock */ fr->ifields[i] = c->first->buffer; c->first->buffer = 0; c->first = c->first->next; } if (n == 1) { fr->ofields[fr->parity] = fr->ifields[0]; fr->ofields[fr->parity^1] = 0; } else if (n == 2) { fr->ofields[fr->parity] = fr->ifields[0]; fr->ofields[fr->parity^1] = fr->ifields[1]; } else if (n == 3) { if (aff == 0) aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1; /* else if (c->verbose) printf("forced aff: %d \n", aff); */ fr->ofields[fr->parity] = fr->ifields[1+aff]; fr->ofields[fr->parity^1] = fr->ifields[1]; } pullup_lock_buffer(fr->ofields[0], 0); pullup_lock_buffer(fr->ofields[1], 1); if (fr->ofields[0] == fr->ofields[1]) { fr->buffer = fr->ofields[0]; pullup_lock_buffer(fr->buffer, 2); return fr; } return fr;}static void copy_field(struct pullup_context *c, struct pullup_buffer *dest, struct pullup_buffer *src, int parity){ int i, j; unsigned char *d, *s; for (i = 0; i < c->nplanes; i++) { s = src->planes[i] + parity*c->stride[i]; d = dest->planes[i] + parity*c->stride[i]; for (j = c->h[i]>>1; j; j--) { memcpy(d, s, c->stride[i]); s += c->stride[i]<<1; d += c->stride[i]<<1; } }}void pullup_pack_frame(struct pullup_context *c, struct pullup_frame *fr){ int i; int par = fr->parity; if (fr->buffer) return; if (fr->length < 2) return; /* FIXME: deal with this */ for (i = 0; i < 2; i++) { if (fr->ofields[i]->lock[i^1]) continue; fr->buffer = fr->ofields[i]; pullup_lock_buffer(fr->buffer, 2); copy_field(c, fr->buffer, fr->ofields[i^1], i^1); return; } fr->buffer = pullup_get_buffer(c, 2); copy_field(c, fr->buffer, fr->ofields[0], 0); copy_field(c, fr->buffer, fr->ofields[1], 1);}void pullup_release_frame(struct pullup_frame *fr){ int i; for (i = 0; i < fr->length; i++) pullup_release_buffer(fr->ifields[i], fr->parity ^ (i&1)); pullup_release_buffer(fr->ofields[0], 0); pullup_release_buffer(fr->ofields[1], 1); if (fr->buffer) pullup_release_buffer(fr->buffer, 2); fr->lock--;}struct pullup_context *pullup_alloc_context(){ struct pullup_context *c; c = calloc(1, sizeof(struct pullup_context)); return c;}void pullup_preinit_context(struct pullup_context *c){ c->bpp = calloc(c->nplanes, sizeof(int)); c->w = calloc(c->nplanes, sizeof(int)); c->h = calloc(c->nplanes, sizeof(int)); c->stride = calloc(c->nplanes, sizeof(int)); c->background = calloc(c->nplanes, sizeof(int));}void pullup_init_context(struct pullup_context *c){ int mp = c->metric_plane; if (c->nbuffers < 10) c->nbuffers = 10; c->buffers = calloc(c->nbuffers, sizeof (struct pullup_buffer)); c->metric_w = (c->w[mp] - ((c->junk_left + c->junk_right) << 3)) >> 3; c->metric_h = (c->h[mp] - ((c->junk_top + c->junk_bottom) << 1)) >> 3; c->metric_offset = c->junk_left*c->bpp[mp] + (c->junk_top<<1)*c->stride[mp]; c->metric_len = c->metric_w * c->metric_h; c->head = make_field_queue(c, 8); c->frame = calloc(1, sizeof (struct pullup_frame)); c->frame->ifields = calloc(3, sizeof (struct pullup_buffer *)); switch(c->format) { case PULLUP_FMT_Y: c->diff = diff_y; c->comb = licomb_y;#ifdef ARCH_X86#ifdef HAVE_MMX if (c->cpu & PULLUP_CPU_MMX) { c->diff = diff_y_mmx; c->comb = licomb_y_mmx; }#endif#endif /* c->comb = qpcomb_y; */ break;#if 0 case PULLUP_FMT_YUY2: c->diff = diff_yuy2; break; case PULLUP_FMT_RGB32: c->diff = diff_rgb32; break;#endif }}void pullup_free_context(struct pullup_context *c){ struct pullup_field *f; free(c->buffers); f = c->head; do { free(f->diffs); free(f->comb); f = f->next; free(f->prev); } while (f != c->head); free(c->frame); free(c);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -