diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 4e11c9ad82..fb5b6deaa7 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -143,6 +143,17 @@ int sws_isSupportedInput(enum PixelFormat pix_fmt); */ int sws_isSupportedOutput(enum PixelFormat pix_fmt); +/** + * Alloctaes an empty SwsContext, this must be filled and passed to sws_init_context(). + * For filling see AVOptions, options.c and sws_setColorspaceDetails(). + */ +struct SwsContext *sws_alloc_context(void); + +/** + * Initializs the swscaler context sws_context. + */ +int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter); + /** * Frees the swscaler context swsContext. * If swsContext is NULL, then does nothing. @@ -161,6 +172,7 @@ void sws_freeContext(struct SwsContext *swsContext); * @param dstFormat the destination image format * @param flags specify which algorithm and options to use for rescaling * @return a pointer to an allocated context, or NULL in case of error + * @deprecated use sws_alloc_context() and sws_init_context() */ struct SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int dstW, int dstH, enum PixelFormat dstFormat, diff --git a/libswscale/utils.c b/libswscale/utils.c index dfb4806416..d2438560d3 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -672,6 +672,8 @@ static void getSubSampleFactors(int *h, int *v, enum PixelFormat format) *v = av_pix_fmt_descriptors[format].log2_chroma_h; } +static int update_flags_cpu(int flags); + int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation) { memcpy(c->srcColorspaceTable, inv_table, sizeof(int)*4); @@ -684,6 +686,10 @@ int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange c->dstRange = dstRange; if (isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1; + c->dstFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[c->dstFormat]); + c->srcFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[c->srcFormat]); + c->flags = update_flags_cpu(c->flags); + ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation); //FIXME factorize @@ -729,36 +735,43 @@ static int update_flags_cpu(int flags) return flags; } -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) -{ - SwsContext *c; +SwsContext *sws_alloc_context(void){ + SwsContext *c= av_mallocz(sizeof(SwsContext)); + + c->av_class = &sws_context_class; + + return c; +} + +int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter){ int i; int usesVFilter, usesHFilter; int unscaled; - int srcRange, dstRange; SwsFilter dummyFilter= {NULL, NULL, NULL, NULL}; + int srcW= c->srcW; + int srcH= c->srcH; + int dstW= c->dstW; + int dstH= c->dstH; + int flags; + enum PixelFormat srcFormat= c->srcFormat; + enum PixelFormat dstFormat= c->dstFormat; + + flags= c->flags = update_flags_cpu(c->flags); #if ARCH_X86 if (flags & SWS_CPU_CAPS_MMX) __asm__ volatile("emms\n\t"::: "memory"); #endif - - flags = update_flags_cpu(flags); if (!rgb15to16) sws_rgb2rgb_init(flags); unscaled = (srcW == dstW && srcH == dstH); - srcRange = handle_jpeg(&srcFormat); - dstRange = handle_jpeg(&dstFormat); - if (!isSupportedIn(srcFormat)) { av_log(NULL, AV_LOG_ERROR, "swScaler: %s is not supported as input pixel format\n", sws_format_name(srcFormat)); - return NULL; + return AVERROR(EINVAL); } if (!isSupportedOut(dstFormat)) { av_log(NULL, AV_LOG_ERROR, "swScaler: %s is not supported as output pixel format\n", sws_format_name(dstFormat)); - return NULL; + return AVERROR(EINVAL); } i= flags & ( SWS_POINT @@ -774,35 +787,24 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, |SWS_BICUBLIN); if(!i || (i & (i-1))) { av_log(NULL, AV_LOG_ERROR, "swScaler: Exactly one scaler algorithm must be chosen\n"); - return NULL; + return AVERROR(EINVAL); } - /* sanity check */ if (srcW<4 || srcH<1 || dstW<8 || dstH<1) { //FIXME check if these are enough and try to lowwer them after fixing the relevant parts of the code av_log(NULL, AV_LOG_ERROR, "swScaler: %dx%d -> %dx%d is invalid scaling dimension\n", srcW, srcH, dstW, dstH); - return NULL; + return AVERROR(EINVAL); } if(srcW > VOFW || dstW > VOFW) { av_log(NULL, AV_LOG_ERROR, "swScaler: Compile-time maximum width is "AV_STRINGIFY(VOFW)" change VOF/VOFW and recompile\n"); - return NULL; + return AVERROR(EINVAL); } if (!dstFilter) dstFilter= &dummyFilter; if (!srcFilter) srcFilter= &dummyFilter; - FF_ALLOCZ_OR_GOTO(NULL, c, sizeof(SwsContext), fail); - - c->av_class = &sws_context_class; - c->srcW= srcW; - c->srcH= srcH; - c->dstW= dstW; - c->dstH= dstH; c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW; c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH; - c->flags= flags; - c->dstFormat= dstFormat; - c->srcFormat= srcFormat; c->dstFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[dstFormat]); c->srcFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[srcFormat]); c->vRounder= 4* 0x0001000100010001ULL; @@ -834,31 +836,21 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, && ((dstW>>c->chrDstHSubSample) <= (srcW>>1) || (flags&SWS_FAST_BILINEAR))) c->chrSrcHSubSample=1; - if (param) { - c->param[0] = param[0]; - c->param[1] = param[1]; - } else { - c->param[0] = - c->param[1] = SWS_PARAM_DEFAULT; - } - // Note the -((-x)>>y) is so that we always round toward +inf. c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample); c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample); c->chrDstW= -((-dstW) >> c->chrDstHSubSample); c->chrDstH= -((-dstH) >> c->chrDstVSubSample); - sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], srcRange, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/, dstRange, 0, 1<<16, 1<<16); - /* unscaled special cases */ - if (unscaled && !usesHFilter && !usesVFilter && (srcRange == dstRange || isAnyRGB(dstFormat))) { + if (unscaled && !usesHFilter && !usesVFilter && (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) { ff_get_unscaled_swscale(c); if (c->swScale) { if (flags&SWS_PRINT_INFO) av_log(c, AV_LOG_INFO, "using unscaled %s -> %s special converter\n", sws_format_name(srcFormat), sws_format_name(dstFormat)); - return c; + return 0; } } @@ -914,7 +906,7 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, #endif if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode) - goto fail; + 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); @@ -1143,11 +1135,45 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, } c->swScale= ff_getSwsFunc(c); - return c; + return 0; +fail: //FIXME replace things by appropriate error codes + return -1; +} -fail: - sws_freeContext(c); - return NULL; +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) +{ + SwsContext *c; + + if(!(c=sws_alloc_context())) + 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; + + if (param) { + c->param[0] = param[0]; + c->param[1] = param[1]; + } else { + c->param[0] = + c->param[1] = SWS_PARAM_DEFAULT; + } + 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); + + if(sws_init_context(c, srcFilter, dstFilter) < 0){ + sws_freeContext(c); + return NULL; + } + + return c; } SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,