Newer
Older
if (flags & SWS_FAST_BILINEAR) {
if (c->canMMX2BeUsed) {
c->lumXInc += 20;
c->chrXInc += 20;
}
// we don't use the x86 asm scaler if MMX is available
else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) {
c->lumXInc = ((int64_t)(srcW - 2) << 16) / (dstW - 2) - 20;
c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;
}
}
/* precalculate horizontal scaler filter coefficients */
{
// can't downscale !!!
if (c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR)) {
c->lumMmx2FilterCodeSize = initMMX2HScaler(dstW, c->lumXInc, NULL,
NULL, NULL, 8);
c->chrMmx2FilterCodeSize = initMMX2HScaler(c->chrDstW, c->chrXInc,
NULL, NULL, NULL, 4);
#ifdef MAP_ANONYMOUS
c->lumMmx2FilterCode = mmap(NULL, c->lumMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
c->chrMmx2FilterCode = mmap(NULL, c->chrMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#elif HAVE_VIRTUALALLOC
c->lumMmx2FilterCode = VirtualAlloc(NULL, c->lumMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
c->chrMmx2FilterCode = VirtualAlloc(NULL, c->chrMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
c->lumMmx2FilterCode = av_malloc(c->lumMmx2FilterCodeSize);
c->chrMmx2FilterCode = av_malloc(c->chrMmx2FilterCodeSize);
#endif
Reimar Döffinger
committed
if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode)
Michael Niedermayer
committed
return AVERROR(ENOMEM);
FF_ALLOCZ_OR_GOTO(c, c->hLumFilter, (dstW / 8 + 8) * sizeof(int16_t), fail);
FF_ALLOCZ_OR_GOTO(c, c->hChrFilter, (c->chrDstW / 4 + 8) * sizeof(int16_t), fail);
FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW / 2 / 8 + 8) * sizeof(int32_t), fail);
FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW / 2 / 4 + 8) * sizeof(int32_t), fail);
initMMX2HScaler(dstW, c->lumXInc, c->lumMmx2FilterCode,
c->hLumFilter, c->hLumFilterPos, 8);
initMMX2HScaler(c->chrDstW, c->chrXInc, c->chrMmx2FilterCode,
c->hChrFilter, c->hChrFilterPos, 4);
#ifdef MAP_ANONYMOUS
mprotect(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize, PROT_EXEC | PROT_READ);
mprotect(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize, PROT_EXEC | PROT_READ);
#endif
} else
#endif /* HAVE_MMXEXT && HAVE_INLINE_ASM */
{
const int filterAlign =
(HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 4 :
(HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
1;
if (initFilter(&c->hLumFilter, &c->hLumFilterPos,
&c->hLumFilterSize, c->lumXInc,
srcW, dstW, filterAlign, 1 << 14,
(flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
cpu_flags, srcFilter->lumH, dstFilter->lumH,
c->param, 1) < 0)
goto fail;
if (initFilter(&c->hChrFilter, &c->hChrFilterPos,
&c->hChrFilterSize, c->chrXInc,
c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,
(flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
cpu_flags, srcFilter->chrH, dstFilter->chrH,
c->param, 1) < 0)
goto fail;
}
} // initialize horizontal stuff
/* precalculate vertical scaler filter coefficients */
{
const int filterAlign =
(HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 2 :
(HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
1;
if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
(flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
cpu_flags, srcFilter->lumV, dstFilter->lumV,
c->param, 0) < 0)
goto fail;
if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,
c->chrYInc, c->chrSrcH, c->chrDstH,
filterAlign, (1 << 12),
(flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
cpu_flags, srcFilter->chrV, dstFilter->chrV,
c->param, 0) < 0)
goto fail;
#if HAVE_ALTIVEC
FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof(vector signed short) * c->vLumFilterSize * c->dstH, fail);
FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof(vector signed short) * c->vChrFilterSize * c->chrDstH, fail);
for (i = 0; i < c->vLumFilterSize * c->dstH; i++) {
int j;
short *p = (short *)&c->vYCoeffsBank[i];
p[j] = c->vLumFilter[i];
}
for (i = 0; i < c->vChrFilterSize * c->chrDstH; i++) {
int j;
short *p = (short *)&c->vCCoeffsBank[i];
p[j] = c->vChrFilter[i];
}
#endif
}
// calculate buffer sizes so that they won't run out while handling these damn slices
c->vLumBufSize = c->vLumFilterSize;
c->vChrBufSize = c->vChrFilterSize;
for (i = 0; i < dstH; i++) {
int chrI = (int64_t)i * c->chrDstH / dstH;
int nextSlice = FFMAX(c->vLumFilterPos[i] + c->vLumFilterSize - 1,
((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)
<< c->chrSrcVSubSample));
nextSlice >>= c->chrSrcVSubSample;
nextSlice <<= c->chrSrcVSubSample;
if (c->vLumFilterPos[i] + c->vLumBufSize < nextSlice)
c->vLumBufSize = nextSlice - c->vLumFilterPos[i];
if (c->vChrFilterPos[chrI] + c->vChrBufSize <
(nextSlice >> c->chrSrcVSubSample))
c->vChrBufSize = (nextSlice >> c->chrSrcVSubSample) -
c->vChrFilterPos[chrI];
}
/* Allocate pixbufs (we use dynamic allocation because otherwise we would
* need to allocate several megabytes to handle all possible cases) */
FF_ALLOC_OR_GOTO(c, c->lumPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))
FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
/* Note we need at least one pixel more at the end because of the MMX code
* (just in case someone wants to replace the 4000/8000). */
/* align at 16 bytes for AltiVec */
for (i = 0; i < c->vLumBufSize; i++) {
FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i + c->vLumBufSize],
dst_stride + 16, fail);
c->lumPixBuf[i] = c->lumPixBuf[i + c->vLumBufSize];
}
// 64 / (c->dstBpc & ~7) is the same as 16 / sizeof(scaling_intermediate)
c->uv_off_px = dst_stride_px + 64 / (c->dstBpc & ~7);
for (i = 0; i < c->vChrBufSize; i++) {
FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i + c->vChrBufSize],
dst_stride * 2 + 32, fail);
c->chrUPixBuf[i] = c->chrUPixBuf[i + c->vChrBufSize];
c->chrVPixBuf[i] = c->chrVPixBuf[i + c->vChrBufSize]
= c->chrUPixBuf[i] + (dst_stride >> 1) + 8;
}
if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
for (i = 0; i < c->vLumBufSize; i++) {
FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i + c->vLumBufSize],
dst_stride + 16, fail);
c->alpPixBuf[i] = c->alpPixBuf[i + c->vLumBufSize];
}
// try to avoid drawing green stuff between the right end and the stride end
for (i = 0; i < c->vChrBufSize; i++)
memset(c->chrUPixBuf[i], 64, dst_stride * 2 + 1);
assert(c->chrDstH <= dstH);
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
if (flags & SWS_PRINT_INFO) {
if (flags & SWS_FAST_BILINEAR)
av_log(c, AV_LOG_INFO, "FAST_BILINEAR scaler, ");
else if (flags & SWS_BILINEAR)
av_log(c, AV_LOG_INFO, "BILINEAR scaler, ");
else if (flags & SWS_BICUBIC)
av_log(c, AV_LOG_INFO, "BICUBIC scaler, ");
else if (flags & SWS_X)
av_log(c, AV_LOG_INFO, "Experimental scaler, ");
else if (flags & SWS_POINT)
av_log(c, AV_LOG_INFO, "Nearest Neighbor / POINT scaler, ");
else if (flags & SWS_AREA)
av_log(c, AV_LOG_INFO, "Area Averaging scaler, ");
else if (flags & SWS_BICUBLIN)
av_log(c, AV_LOG_INFO, "luma BICUBIC / chroma BILINEAR scaler, ");
else if (flags & SWS_GAUSS)
av_log(c, AV_LOG_INFO, "Gaussian scaler, ");
else if (flags & SWS_SINC)
av_log(c, AV_LOG_INFO, "Sinc scaler, ");
else if (flags & SWS_LANCZOS)
av_log(c, AV_LOG_INFO, "Lanczos scaler, ");
else if (flags & SWS_SPLINE)
av_log(c, AV_LOG_INFO, "Bicubic spline scaler, ");
else
av_log(c, AV_LOG_INFO, "ehh flags invalid?! ");
av_log(c, AV_LOG_INFO, "from %s to %s%s ",
sws_format_name(srcFormat),
#ifdef DITHER1XBPP
dstFormat == PIX_FMT_BGR555 || dstFormat == PIX_FMT_BGR565 ||
Janusz Krzysztofik
committed
dstFormat == PIX_FMT_RGB444BE || dstFormat == PIX_FMT_RGB444LE ||
dstFormat == PIX_FMT_BGR444BE || dstFormat == PIX_FMT_BGR444LE ?
"dithered " : "",
#else
"",
#endif
sws_format_name(dstFormat));
if (HAVE_MMXEXT && cpu_flags & AV_CPU_FLAG_MMXEXT)
av_log(c, AV_LOG_INFO, "using MMX2\n");
else if (HAVE_AMD3DNOW && cpu_flags & AV_CPU_FLAG_3DNOW)
av_log(c, AV_LOG_INFO, "using 3DNOW\n");
else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX)
av_log(c, AV_LOG_INFO, "using MMX\n");
else if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC)
av_log(c, AV_LOG_INFO, "using AltiVec\n");
else
av_log(c, AV_LOG_INFO, "using C\n");
av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
av_log(c, AV_LOG_DEBUG,
"lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
av_log(c, AV_LOG_DEBUG,
"chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH,
c->chrXInc, c->chrYInc);
}
c->swScale = ff_getSwsFunc(c);
Michael Niedermayer
committed
return 0;
fail: // FIXME replace things by appropriate error codes
Michael Niedermayer
committed
return -1;
}
#if FF_API_SWS_GETCONTEXT
Michael Niedermayer
committed
SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat,
int dstW, int dstH, enum PixelFormat dstFormat,
int flags, SwsFilter *srcFilter,
SwsFilter *dstFilter, const double *param)
Michael Niedermayer
committed
{
SwsContext *c;
if (!(c = sws_alloc_context()))
Michael Niedermayer
committed
return NULL;
c->flags = flags;
c->srcW = srcW;
c->srcH = srcH;
c->dstW = dstW;
c->dstH = dstH;
c->srcRange = handle_jpeg(&srcFormat);
c->dstRange = handle_jpeg(&dstFormat);
c->srcFormat = srcFormat;
c->dstFormat = dstFormat;
Michael Niedermayer
committed
if (param) {
c->param[0] = param[0];
c->param[1] = param[1];
}
sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange,
ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
c->dstRange, 0, 1 << 16, 1 << 16);
Michael Niedermayer
committed
if (sws_init_context(c, srcFilter, dstFilter) < 0) {
Michael Niedermayer
committed
sws_freeContext(c);
return NULL;
}
return c;
}
SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
float lumaSharpen, float chromaSharpen,
float chromaHShift, float chromaVShift,
int verbose)
{
SwsFilter *filter = av_malloc(sizeof(SwsFilter));
if (!filter)
return NULL;
if (lumaGBlur != 0.0) {
filter->lumH = sws_getGaussianVec(lumaGBlur, 3.0);
filter->lumV = sws_getGaussianVec(lumaGBlur, 3.0);
} else {
filter->lumH = sws_getIdentityVec();
filter->lumV = sws_getIdentityVec();
}
if (chromaGBlur != 0.0) {
filter->chrH = sws_getGaussianVec(chromaGBlur, 3.0);
filter->chrV = sws_getGaussianVec(chromaGBlur, 3.0);
} else {
filter->chrH = sws_getIdentityVec();
filter->chrV = sws_getIdentityVec();
}
if (chromaSharpen != 0.0) {
SwsVector *id = sws_getIdentityVec();
sws_scaleVec(filter->chrH, -chromaSharpen);
sws_scaleVec(filter->chrV, -chromaSharpen);
sws_addVec(filter->chrH, id);
sws_addVec(filter->chrV, id);
sws_freeVec(id);
}
if (lumaSharpen != 0.0) {
SwsVector *id = sws_getIdentityVec();
sws_scaleVec(filter->lumH, -lumaSharpen);
sws_scaleVec(filter->lumV, -lumaSharpen);
sws_addVec(filter->lumH, id);
sws_addVec(filter->lumV, id);
sws_freeVec(id);
}
if (chromaHShift != 0.0)
sws_shiftVec(filter->chrH, (int)(chromaHShift + 0.5));
if (chromaVShift != 0.0)
sws_shiftVec(filter->chrV, (int)(chromaVShift + 0.5));
sws_normalizeVec(filter->chrH, 1.0);
sws_normalizeVec(filter->chrV, 1.0);
sws_normalizeVec(filter->lumH, 1.0);
sws_normalizeVec(filter->lumV, 1.0);
if (verbose)
sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG);
if (verbose)
sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG);
return filter;
}
SwsVector *sws_allocVec(int length)
{
SwsVector *vec = av_malloc(sizeof(SwsVector));
if (!vec)
return NULL;
vec->length = length;
vec->coeff = av_malloc(sizeof(double) * length);
if (!vec->coeff)
av_freep(&vec);
return vec;
}
SwsVector *sws_getGaussianVec(double variance, double quality)
{
const int length = (int)(variance * quality + 0.5) | 1;
int i;
double middle = (length - 1) * 0.5;
SwsVector *vec = sws_allocVec(length);
if (!vec)
return NULL;
for (i = 0; i < length; i++) {
double dist = i - middle;
vec->coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
sqrt(2 * variance * M_PI);
}
sws_normalizeVec(vec, 1.0);
return vec;
}
SwsVector *sws_getConstVec(double c, int length)
{
int i;
SwsVector *vec = sws_allocVec(length);
if (!vec)
return NULL;
for (i = 0; i < length; i++)
vec->coeff[i] = c;
return vec;
}
SwsVector *sws_getIdentityVec(void)
{
return sws_getConstVec(1.0, 1);
}
static double sws_dcVec(SwsVector *a)
{
int i;
for (i = 0; i < a->length; i++)
sum += a->coeff[i];
return sum;
}
void sws_scaleVec(SwsVector *a, double scalar)
{
int i;
for (i = 0; i < a->length; i++)
a->coeff[i] *= scalar;
}
void sws_normalizeVec(SwsVector *a, double height)
{
sws_scaleVec(a, height / sws_dcVec(a));
}
static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b)
{
int length = a->length + b->length - 1;
int i, j;
SwsVector *vec = sws_getConstVec(0.0, length);
if (!vec)
return NULL;
for (i = 0; i < a->length; i++) {
for (j = 0; j < b->length; j++) {
vec->coeff[i + j] += a->coeff[i] * b->coeff[j];
}
}
return vec;
}
static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
{
int length = FFMAX(a->length, b->length);
int i;
SwsVector *vec = sws_getConstVec(0.0, length);
if (!vec)
return NULL;
for (i = 0; i < a->length; i++)
vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
for (i = 0; i < b->length; i++)
vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] += b->coeff[i];
return vec;
}
static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b)
{
int length = FFMAX(a->length, b->length);
int i;
SwsVector *vec = sws_getConstVec(0.0, length);
if (!vec)
return NULL;
for (i = 0; i < a->length; i++)
vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
for (i = 0; i < b->length; i++)
vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] -= b->coeff[i];
return vec;
}
/* shift left / or right if "shift" is negative */
static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
{
int length = a->length + FFABS(shift) * 2;
int i;
SwsVector *vec = sws_getConstVec(0.0, length);
if (!vec)
return NULL;
for (i = 0; i < a->length; i++) {
vec->coeff[i + (length - 1) / 2 -
(a->length - 1) / 2 - shift] = a->coeff[i];
}
return vec;
}
void sws_shiftVec(SwsVector *a, int shift)
{
SwsVector *shifted = sws_getShiftedVec(a, shift);
av_free(a->coeff);
a->coeff = shifted->coeff;
a->length = shifted->length;
av_free(shifted);
}
void sws_addVec(SwsVector *a, SwsVector *b)
{
SwsVector *sum = sws_sumVec(a, b);
av_free(a->coeff);
a->coeff = sum->coeff;
a->length = sum->length;
av_free(sum);
}
void sws_subVec(SwsVector *a, SwsVector *b)
{
SwsVector *diff = sws_diffVec(a, b);
av_free(a->coeff);
a->coeff = diff->coeff;
a->length = diff->length;
av_free(diff);
}
void sws_convVec(SwsVector *a, SwsVector *b)
{
SwsVector *conv = sws_getConvVec(a, b);
av_free(a->coeff);
a->coeff = conv->coeff;
a->length = conv->length;
av_free(conv);
}
SwsVector *sws_cloneVec(SwsVector *a)
{
int i;
SwsVector *vec = sws_allocVec(a->length);
if (!vec)
return NULL;
for (i = 0; i < a->length; i++)
vec->coeff[i] = a->coeff[i];
return vec;
}
void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level)
{
int i;
double max = 0;
double min = 0;
double range;
for (i = 0; i < a->length; i++)
if (a->coeff[i] > max)
max = a->coeff[i];
for (i = 0; i < a->length; i++)
if (a->coeff[i] < min)
min = a->coeff[i];
for (i = 0; i < a->length; i++) {
int x = (int)((a->coeff[i] - min) * 60.0 / range + 0.5);
av_log(log_ctx, log_level, "%1.3f ", a->coeff[i]);
for (; x > 0; x--)
av_log(log_ctx, log_level, " ");
av_log(log_ctx, log_level, "|\n");
}
}
void sws_freeVec(SwsVector *a)
{
av_freep(&a->coeff);
av_free(a);
}
void sws_freeFilter(SwsFilter *filter)
{
if (!filter)
return;
if (filter->lumH)
sws_freeVec(filter->lumH);
if (filter->lumV)
sws_freeVec(filter->lumV);
if (filter->chrH)
sws_freeVec(filter->chrH);
if (filter->chrV)
sws_freeVec(filter->chrV);
av_free(filter);
}
void sws_freeContext(SwsContext *c)
{
int i;
if (c->lumPixBuf) {
for (i = 0; i < c->vLumBufSize; i++)
av_freep(&c->lumPixBuf[i]);
av_freep(&c->lumPixBuf);
}
if (c->chrUPixBuf) {
for (i = 0; i < c->vChrBufSize; i++)
av_freep(&c->chrUPixBuf[i]);
av_freep(&c->chrUPixBuf);
av_freep(&c->chrVPixBuf);
}
if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
for (i = 0; i < c->vLumBufSize; i++)
av_freep(&c->alpPixBuf[i]);
av_freep(&c->alpPixBuf);
}
av_freep(&c->vLumFilter);
av_freep(&c->vChrFilter);
av_freep(&c->hLumFilter);
av_freep(&c->hChrFilter);
#if HAVE_ALTIVEC
av_freep(&c->vYCoeffsBank);
av_freep(&c->vCCoeffsBank);
#endif
av_freep(&c->vLumFilterPos);
av_freep(&c->vChrFilterPos);
av_freep(&c->hLumFilterPos);
av_freep(&c->hChrFilterPos);
#if HAVE_MMX
#ifdef MAP_ANONYMOUS
if (c->lumMmx2FilterCode)
munmap(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize);
if (c->chrMmx2FilterCode)
munmap(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize);
#elif HAVE_VIRTUALALLOC
if (c->lumMmx2FilterCode)
VirtualFree(c->lumMmx2FilterCode, 0, MEM_RELEASE);
if (c->chrMmx2FilterCode)
VirtualFree(c->chrMmx2FilterCode, 0, MEM_RELEASE);
#else
av_free(c->lumMmx2FilterCode);
av_free(c->chrMmx2FilterCode);
#endif
c->lumMmx2FilterCode = NULL;
c->chrMmx2FilterCode = NULL;
#endif /* HAVE_MMX */
av_freep(&c->yuvTable);
av_free(c->formatConvBuffer);
av_free(c);
}
struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW,
int srcH, enum PixelFormat srcFormat,
int dstW, int dstH,
enum PixelFormat dstFormat, int flags,
SwsFilter *srcFilter,
SwsFilter *dstFilter,
const double *param)
{
static const double default_param[2] = { SWS_PARAM_DEFAULT,
SWS_PARAM_DEFAULT };
if (!param)
param = default_param;
if (context &&
(context->srcW != srcW ||
context->srcH != srcH ||
context->srcFormat != srcFormat ||
context->dstW != dstW ||
context->dstH != dstH ||
context->dstFormat != dstFormat ||
context->flags != flags ||
context->param[0] != param[0] ||
context->param[1] != param[1])) {
sws_freeContext(context);
context = NULL;
}
if (!context) {
if (!(context = sws_alloc_context()))
return NULL;
context->srcW = srcW;
context->srcH = srcH;
context->srcRange = handle_jpeg(&srcFormat);
context->srcFormat = srcFormat;
context->dstW = dstW;
context->dstH = dstH;
context->dstRange = handle_jpeg(&dstFormat);
context->dstFormat = dstFormat;
context->flags = flags;
context->param[0] = param[0];
context->param[1] = param[1];
sws_setColorspaceDetails(context, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
context->srcRange,
ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
context->dstRange, 0, 1 << 16, 1 << 16);
if (sws_init_context(context, srcFilter, dstFilter) < 0) {
sws_freeContext(context);
return NULL;
}
}
return context;
}