diff --git a/libswscale/slice.c b/libswscale/slice.c index 3a8001fdeb..242367dfd5 100644 --- a/libswscale/slice.c +++ b/libswscale/slice.c @@ -224,12 +224,12 @@ int ff_init_filters(SwsContext * c) res = alloc_slice(&c->slice[0], c->srcFormat, c->srcH, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0); if (res < 0) goto cleanup; for (i = 1; i < c->numSlice-1; ++i) { - res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize, c->vChrFilterSize, c->chrSrcHSubSample, c->chrSrcVSubSample, 0); + res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize + MAX_LINES_AHEAD, c->vChrFilterSize + MAX_LINES_AHEAD, c->chrSrcHSubSample, c->chrSrcVSubSample, 0); if (res < 0) goto cleanup; res = alloc_lines(&c->slice[i], FFALIGN(c->srcW*2+78, 16), c->srcW); if (res < 0) goto cleanup; } - res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize, c->vChrFilterSize, c->chrDstHSubSample, c->chrDstVSubSample, 1); + res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize + MAX_LINES_AHEAD, c->vChrFilterSize + MAX_LINES_AHEAD, c->chrDstHSubSample, c->chrDstVSubSample, 1); if (res < 0) goto cleanup; res = alloc_lines(&c->slice[i], dst_stride, c->dstW); if (res < 0) goto cleanup; diff --git a/libswscale/swscale.c b/libswscale/swscale.c index e96c7eead1..e5bab9cd95 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -379,6 +379,8 @@ static int swscale(SwsContext *c, const uint8_t *src[], SwsSlice *src_slice = &c->slice[lumStart]; SwsSlice *dst_slice = &c->slice[c->numSlice-1]; SwsFilterDescriptor *desc = c->desc; + int hasLumHoles = 1; + int hasChrHoles = 1; if (!usePal(c->srcFormat)) { @@ -487,21 +489,28 @@ static int swscale(SwsContext *c, const uint8_t *src[], int lastChrSrcY = FFMIN(c->chrSrcH, firstChrSrcY + vChrFilterSize) - 1; int enough_lines; int i; + int posY, cPosY, firstPosY, lastPosY, firstCPosY, lastCPosY; // handle holes (FAST_BILINEAR & weird filters) if (firstLumSrcY > lastInLumBuf) { + hasLumHoles = lastInLumBuf != firstLumSrcY - 1; lastInLumBuf = firstLumSrcY - 1; - dst_slice->plane[0].sliceY = lastInLumBuf + 1; - dst_slice->plane[3].sliceY = lastInLumBuf + 1; - dst_slice->plane[0].sliceH = - dst_slice->plane[3].sliceH = 0; + if (hasLumHoles) { + dst_slice->plane[0].sliceY = lastInLumBuf + 1; + dst_slice->plane[3].sliceY = lastInLumBuf + 1; + dst_slice->plane[0].sliceH = + dst_slice->plane[3].sliceH = 0; + } } if (firstChrSrcY > lastInChrBuf) { + hasChrHoles = lastInChrBuf != firstChrSrcY - 1; lastInChrBuf = firstChrSrcY - 1; - dst_slice->plane[1].sliceY = lastInChrBuf + 1; - dst_slice->plane[2].sliceY = lastInChrBuf + 1; - dst_slice->plane[1].sliceH = - dst_slice->plane[2].sliceH = 0; + if (hasChrHoles) { + dst_slice->plane[1].sliceY = lastInChrBuf + 1; + dst_slice->plane[2].sliceY = lastInChrBuf + 1; + dst_slice->plane[1].sliceH = + dst_slice->plane[2].sliceH = 0; + } } av_assert0(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1); av_assert0(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1); @@ -524,17 +533,39 @@ static int swscale(SwsContext *c, const uint8_t *src[], } #if NEW_FILTER - ff_rotate_slice(dst_slice, lastLumSrcY, lastChrSrcY); + posY = dst_slice->plane[0].sliceY + dst_slice->plane[0].sliceH; + if (posY <= lastLumSrcY && !hasLumHoles) { + firstPosY = FFMAX(firstLumSrcY, posY); + lastPosY = FFMIN(lastLumSrcY + MAX_LINES_AHEAD, srcSliceY + srcSliceH - 1); + } else { + firstPosY = lastInLumBuf + 1; + lastPosY = lastLumSrcY; + } - if (lastInLumBuf < lastLumSrcY) + cPosY = dst_slice->plane[1].sliceY + dst_slice->plane[1].sliceH; + if (cPosY <= lastChrSrcY && !hasChrHoles) { + firstCPosY = FFMAX(firstChrSrcY, cPosY); + lastCPosY = FFMIN(lastChrSrcY + MAX_LINES_AHEAD, FF_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1); + } else { + firstCPosY = lastInChrBuf + 1; + lastCPosY = lastChrSrcY; + } + + ff_rotate_slice(dst_slice, lastPosY, lastCPosY); + + if (posY < lastLumSrcY + 1) { for (i = lumStart; i < lumEnd; ++i) - desc[i].process(c, &desc[i], lastInLumBuf + 1, lastLumSrcY - lastInLumBuf); + desc[i].process(c, &desc[i], firstPosY, lastPosY - firstPosY + 1); + } + lumBufIndex += lastLumSrcY - lastInLumBuf; lastInLumBuf = lastLumSrcY; - if (lastInChrBuf < lastChrSrcY) + if (cPosY < lastChrSrcY + 1) { for (i = chrStart; i < chrEnd; ++i) - desc[i].process(c, &desc[i], lastInChrBuf + 1, lastChrSrcY - lastInChrBuf); + desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1); + } + chrBufIndex += lastChrSrcY - lastInChrBuf; lastInChrBuf = lastChrSrcY; diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 2e69e27901..f46bb78bd7 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -1019,7 +1019,6 @@ int ff_free_filters(SwsContext *c); */ int ff_rotate_slice(SwsSlice *s, int lum, int chr); - /// initializes lum pixel format conversion descriptor int ff_init_desc_fmt_convert(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst, uint32_t *pal); @@ -1034,4 +1033,7 @@ int ff_init_desc_chscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst int ff_init_desc_no_chr(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst); +//number of extra lines to process +#define MAX_LINES_AHEAD 4 + #endif /* SWSCALE_SWSCALE_INTERNAL_H */