📄 yuvkineco.c
字号:
} } data += width * height; if (pln == 0) { width /= CWDIV(y4m_si_get_chroma(&h->_.si)); height /= CHDIV(y4m_si_get_chroma(&h->_.si)); } } return n;}static intputframe(YfTask_t *h, int c, YfFrame_t *frame){ if (c <= 1) { if (c) deinterlace(h, frame->data, h->_.width, h->_.height, h->u.noise.level0); } else { if (0 <= h->deintl) { int n; int bytes = FRAMEBYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height); YfFrame_t *fdst = (YfFrame_t *)((char *)h->frame + (h->nframes * bytes)); y4m_copy_frame_info(&fdst->fi, &frame->fi); memcpy(fdst->data, frame->data, bytes - sizeof frame->fi); n = deinterlace(h, fdst->data, h->_.width, h->_.height, h->u.noise.level0); if (h->deintl < n) { frame = fdst; c -= 'O' - 'D'; h->deintlframes++; if (n < h->deintlmin) h->deintlmin = n; } else { if (h->nointlmax < n) h->nointlmax = n; } n *= (2 * DEINTLRESO); n /= (bytes - sizeof frame->fi); if (sizeof h->deintldist / sizeof h->deintldist[0] <= n) n = (sizeof h->deintldist / sizeof h->deintldist[0]) - 1; h->deintldist[n]++; } if (h->cytype == 'C') putcy(h, c); } return YfPutFrame(&h->_, frame);}static intdo_frame(YfTaskCore_t *handle, const YfTaskCore_t *h0, const YfFrame_t *frame0){ static const unsigned long fp1001s[] = { 0, 24000, 24024, 25025, 30000, 30030, 50050, 60000, 60060, }; YfTask_t *h = (YfTask_t *)handle; int framebytes = FRAMEBYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height); int iadjust = ((h->_.fpscode == h->fpscode0)? 1: (((int64_t)h->iuse * fp1001s[h->_.fpscode] / fp1001s[h->fpscode0]) - h->iput)); int wdiv = CWDIV(y4m_si_get_chroma(&h->_.si)); int hdiv = CHDIV(y4m_si_get_chroma(&h->_.si)); /* copy frame to buffer */ if (frame0) { int b = h->iget % h->nframes; YfFrame_t *fget = (YfFrame_t *)((char *)h->frame + (b * framebytes)); y4m_copy_frame_info(&fget->fi, &frame0->fi); memcpy(fget->data, frame0->data, framebytes - sizeof frame0->fi); /* get frame summary */ if (h->cytype == 'O' || h->cytype =='N') { /* do nothing */ } else if (!h->iget) { h->framestat[b].odiff = 0 /* 9999999 */; h->framestat[b].ediff = 0 /* 9999999 */; } else { int i, j, d; unsigned int ypre, yget; unsigned int noise; int ipre = (h->iget - 1) % h->nframes; YfFrame_t *fpre = (YfFrame_t *)((char *)h->frame + (ipre * framebytes)); memset(&h->framestat[b], 0, sizeof h->framestat[b]); for (i = h->nfields; i < h->_.height; i += h->nfields) { for (j = 0; j < h->_.width; j++) { ypre = fpre->data[(i * h->_.width) + j]; yget = fget->data[(i * h->_.width) + j]; noise = h->u.noise.level0; if (yget < noise) noise = yget; else if (256 - yget < noise) noise = 256 - yget; if ((d = ypre - yget) < 0) d = -d; h->framestat[b].diffdist[(d < NOISEMAX)? d: NOISEMAX]++; if (noise < d) { d -= noise; h->framestat[b].odiff += (((d * d) + 8) >> 4); } if (1 < h->nfields) { unsigned int ygte; ypre = fpre->data[((i - 1) * h->_.width) + j]; ygte = fget->data[((i - 1) * h->_.width) + j]; if ((d = yget - ygte) < 0) d = -d; if (noise < d) { d -= noise; h->framestat[b].eoediff -= (((d * d) + 16) >> 5); } if ((d = yget - ypre) < 0) d = -d; if (noise < d) { d -= noise; h->framestat[b].eoediff += (((d * d) + 16) >> 5); } ypre = fpre->data[((i + 1) * h->_.width) + j]; ygte = fget->data[((i + 1) * h->_.width) + j]; if ((d = yget - ygte) < 0) d = -d; if (noise < d) { d -= noise; h->framestat[b].eoediff -= (((d * d) + 16) >> 5); } if ((d = yget - ypre) < 0) d = -d; if (noise < d) { d -= noise; h->framestat[b].eoediff += (((d * d) + 16) >> 5); } if ((d = ypre - ygte) < 0) d = -d; if (noise < d) { d -= noise; h->framestat[b].ediff += (((d * d) + 8) >> 4); } } } }#define PER1024PIXEL(p,h,w) (((p)/=(w)), ((p)<<=10), ((p)/=(h))) PER1024PIXEL(h->framestat[b].odiff, ((h->_.height / h->nfields) - 1), h->_.width); if (1 < h->nfields) { PER1024PIXEL(h->framestat[b].ediff, ((h->_.height / 2) - 1), h->_.width); PER1024PIXEL(h->framestat[b].eoediff, ((h->_.height / 2) - 1), h->_.width); } } h->iget++; } if (!h->cytype || h->cytype =='C') { /* 1st try */ /* process frames in buffer */ if (h->iget - h->iuse == h->nframes || !frame0) { int b = h->iuse % h->nframes; int i, idrp; unsigned long dthr = 0; char notdrop[48]; char debugbuf[1024]; debugbuf[0] = '\0'; if (1 < verbose) { MPEG_timecode_t tc; mpeg_timecode(&tc, h->iput, h->_.fpscode, 0.); buf_debug(debugbuf, NULL, "%02d:%02d:%02d ", tc.m, tc.s, tc.f); } { /* get threshold */ unsigned long dmin = 0xffffffffUL, dmax = 0; int imin = -1, imax = -1; for (i = 0; i < h->iget - h->iuse - 1; i++) { unsigned long odiff = h->framestat[(b + i) % h->nframes].odiff; if (1 < verbose) buf_debug(debugbuf, NULL, "%8ld:%-7lu", h->framestat[(b + i) % h->nframes].eoediff, odiff); if (odiff < dmin) { dmin = odiff; imin = i; /* maybe repeated field */ } if (dmax < odiff) { dmax = odiff; imax = i; /* maybe cut changed */ } } for (i = 0; i < h->iget - h->iuse - 1; i++) if (i != imin && i != imax) dthr += h->framestat[(b + i) % h->nframes].odiff; /* sum */ if (0 < i - 2) { dthr /= (i - 2); /* average */ dthr -= dmin; dthr *= h->dthr16; dthr += 15; /* round up */ dthr >>= 4; /* /= 16 */ dthr += dmin; dthr += h->u.noise.level0; } } /* search frame to drop */ memset(notdrop, ((1 < h->nfields)? '2': '0'), sizeof notdrop); notdrop[h->iget - h->iuse - 1] = '\0'; /* check motion top field (or frame of non-interlaced) */ for (i = 0; i < h->iget - h->iuse - 1; i++) if (dthr < h->framestat[(b + i) % h->nframes].odiff) notdrop[i] |= 1; if (1 < h->nfields) { /* check field merged */ int merged = 0;#if 0 /* codes for video editing fade-in/out */ long dmax = -0x7fffffffL, d2nd = -0x7fffffffL, d3rd = -0x7fffffffL; for (i = 1; i < (h->nframes / 2) + 2 && i < h->iget - h->iuse; i++) { long eoediff = h->framestat[(b + i) % h->nframes].eoediff; if (eoediff == -9999999) continue; if (dmax < eoediff) { d3rd = d2nd; d2nd = dmax; dmax = eoediff; } else if (d2nd < eoediff) { d3rd = d2nd; d2nd = eoediff; } else if (d3rd < eoediff) { d3rd = eoediff; } } if (d3rd == -0x7fffffffL) d3rd = 0; if (1 < verbose) buf_debug(debugbuf, NULL, "%6ld", d3rd); for (i = 1; i < (h->nframes / 2) + 2 && i < h->iget - h->iuse; i++) if (h->framestat[(b + i) % h->nframes].eoediff < d3rd - (long)dthr)#else for (i = 1; i < h->iget - h->iuse - 1; i++) if (h->framestat[(b + i) % h->nframes].eoediff < -(long)dthr)#endif { merged = 1; notdrop[i - 1] &= ~2; notdrop[i ] &= ~2; } if (!merged) for (i = 0; i < h->iget - h->iuse - 1; i++) notdrop[i] &= ~2; } idrp = h->nframes / 2; if (h->iget - h->iuse - 1 < idrp) idrp = h->iget - h->iuse - 1; while (0 <= idrp && notdrop[idrp] != '0') idrp--; if (idrp < 0) { idrp = h->nframes / 2; if (h->iget - h->iuse - 1 < idrp) idrp = h->iget - h->iuse - 1; while (0 <= idrp && (notdrop[idrp] & 1)) idrp--; } if (idrp < 0 && (h->nframes / 2) + 1 < h->iget - h->iuse - 1) { idrp = (h->nframes / 2) + 1; while (idrp < h->iget - h->iuse - 1 && (notdrop[idrp] & 1)) idrp++; if (idrp == h->iget - h->iuse - 1) { idrp = h->nframes / 2; goto DONE; } } if (idrp == h->nframes / 2) { unsigned long noisetotal; int bdrp;#if 0 int diff1024;#endif for (i = 0; i < idrp; i++) if (notdrop[i] == '0') goto DONE; /* calculate noise level */ while ((noisetotal = (h->u.noise.total + (((h->_.height / h->nfields) - 1) * h->_.width))) < h->u.noise.total) /* overflow */ for (h->u.noise.total = 0, i = 0; i <= NOISEMAX; i++) h->u.noise.total += (h->u.noise.dist[i] >>= 1); h->u.noise.total = noisetotal; bdrp = (b + idrp) % h->nframes; for (i = 0; i <= NOISEMAX; i++) h->u.noise.dist[i] += h->framestat[bdrp].diffdist[i]; noisetotal = NOISERATIO(noisetotal); for (i = 0; i <= NOISEMAX; i++) { if (noisetotal < h->u.noise.dist[i]) break; noisetotal -= h->u.noise.dist[i]; }#if 0 diff1024 = (i - h->u.noise.level) * 1024;#endif h->u.noise.level = i;#if 0 if (diff1024) { for (i = 0; i < h->nframes; i++) { if (diff1024 < -(int)h->framestat[i].odiff) h->framestat[i].odiff = 0; else h->framestat[i].odiff += diff1024; } if (1 < h->nfields) for (i = 0; i < h->nframes; i++) { if (diff1024 < -(int)h->framestat[i].ediff) h->framestat[i].ediff = 0; else h->framestat[i].ediff += diff1024; } }#endif } DONE: if (1 < verbose) buf_debug(debugbuf, NULL, "%3d%7lu %s%3d%3u", iadjust, dthr, notdrop, idrp, h->u.noise.level); /* reconstruct frame field merged */ if (1 < h->nfields) { int isrc, isrc0; isrc0 = ((0 < iadjust && 0 < idrp)? (idrp - 1): idrp); isrc = idrp + (h->nframes / 4) - 1; if (h->iget - h->iuse - 2 < isrc) isrc = h->iget - h->iuse - 2; for (; isrc0 <= isrc; --isrc) { int bsrc = (b + isrc) % h->nframes; int bdst = (bsrc + 1) % h->nframes; if ((isrc < idrp + (h->nframes / 4) - 1 || dthr < h->framestat[bdst].ediff) && h->framestat[bdst].eoediff <= 0 && h->framestat[bdst].eoediff != -9999999) { YfFrame_t *fsrc = (YfFrame_t *)((char *)h->frame + (bsrc * framebytes)); YfFrame_t *fdst = (YfFrame_t *)((char *)h->frame + (bdst * framebytes)); for (i = 1; i < h->_.height; i += 2) /* copy bottom field Y */ memcpy(&fdst->data[i * h->_.width], &fsrc->data[i * h->_.width], h->_.width); for (i = (h->_.height * wdiv) + 1; i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[i * h->_.width / wdiv], &fsrc->data[i * h->_.width / wdiv], h->_.width / wdiv); if (1 < verbose) buf_debug(debugbuf, NULL, "%2d", isrc + 1); h->framestat[bdst].eoediff = -9999999; } else { if (1 < verbose) buf_debug(debugbuf, NULL, " -"); } } } if (1 < verbose) buf_debug(debugbuf, NULL, "\n"); /* output frames */ for (i = 0; i < idrp; i++) { int ret; YfFrame_t *fout = (YfFrame_t *)((char *)h->frame + (b * framebytes)); if ((ret = putframe(h, 'O', fout))) return ret; h->iput++; h->iuse++; b = h->iuse % h->nframes; } if (h->iuse < h->iget) { YfFrame_t *fout = (YfFrame_t *)((char *)h->frame + (b * framebytes)); if (iadjust <= 0) { if (h->cytype == 'C') putcy(h, '_'); } else { int ret; if ((ret = putframe(h, 'o', fout))) return ret; h->iput++; } h->iuse++; } } } else { /* retry */ int i, c; YfFrame_t *fsrc, *fdst; int deintl = 0; while (!*h->u.cy.p) { char *s, *d; char buff[128]; d = h->u.cy.p = h->u.cy.buff; if (!fgets(buff, sizeof buff, h->cyfp)) { perror("cycle list"); return 1; } for (s = buff; (c = *s); s++) { /* FIXME: frame# should be checked */ if (c == '#') break; if (isalpha(c) || (c == '_' && h->cytype == 'O')) { if (h->u.cy.buff + 30 <= d) { WWARN("too long line in cycle list."); break; } *d++ = c; } } *d = '\0'; } fsrc = (YfFrame_t *)((char *)h->frame + (((h->iuse - 1) % h->nframes) * framebytes)); fdst = (YfFrame_t *)((char *)h->frame + (((h->iuse) % h->nframes) * framebytes)); h->iuse++; c = *h->u.cy.p++; if (c == '_') return 0; if (islower(c)) { if (iadjust <= 0) return 0; c += 'A' - 'a'; } switch (c) { case 'D': case 'M': if (h->cytype == 'N') goto DEINTLDECIDED; /* else do as E, N */ case 'E': case 'N': deintl = 1; DEINTLDECIDED: c += 'O' - 'D'; /* D->O, M->X, E->P(do as O), N->Y */ break; } i = 0; switch (c) { case 'X': if (h->cytype == 'N') break; /* else do as Y */ case 'Y': for (i = 1; i < h->_.height; i += 2) /* copy bottom field Y */ memcpy(&fdst->data[i * h->_.width], &fsrc->data[i * h->_.width], h->_.width); for (i = (h->_.height * wdiv) + 1; i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[i * h->_.width / wdiv], &fsrc->data[i * h->_.width / wdiv], h->_.width / wdiv); break; case 'T': for (i = 0; i < h->_.height; i += 2) /* duplicate top field Y */ memcpy(&fdst->data[(i + 1) * h->_.width], &fdst->data[(i) * h->_.width], h->_.width); for (i = (h->_.height * wdiv); i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[(i + 1) * h->_.width / wdiv], &fsrc->data[(i) * h->_.width / wdiv], h->_.width / wdiv); break; case 'B': for (i = 0; i < h->_.height; i += 2) /* duplicate bottom field Y */ memcpy(&fdst->data[(i) * h->_.width], &fdst->data[(i + 1) * h->_.width], h->_.width); for (i = (h->_.height * wdiv); i < h->_.height * (wdiv + (2 / hdiv)); i += 2) /* UV */ memcpy(&fdst->data[(i) * h->_.width / wdiv], &fsrc->data[(i + 1) * h->_.width / wdiv], h->_.width / wdiv); break; } if ((c = putframe(h, deintl, fdst))) return c; h->iput++; if (i || deintl) memcpy(fdst->data, frame0->data, framebytes - sizeof frame0->fi); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -