From 8e05f9217ae567a26ea71dd29acd79b1631ae593 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 30 Aug 2015 23:58:37 +0200 Subject: swscale/utils: Split scaling if possible and yuv->yuv with different matrixes is requested This uses a RGB intermediate, a more optimal solution would be to perform the rematrixing directly in subsampled YUV, this is quite a bit more complicated though Fixes Ticket4805 Signed-off-by: Michael Niedermayer --- libswscale/utils.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'libswscale/utils.c') diff --git a/libswscale/utils.c b/libswscale/utils.c index 181a48ad21..53f68db1b3 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -855,8 +855,73 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], if (need_reinit && (c->srcBpc == 8 || !isYUV(c->srcFormat))) ff_sws_init_range_convert(c); - if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat))) + if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat))) { + if (!c->cascaded_context[0] && + memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4) && + c->srcW && c->srcH && c->dstW && c->dstH) { + enum AVPixelFormat tmp_format; + int tmp_width, tmp_height; + int srcW = c->srcW; + int srcH = c->srcH; + int dstW = c->dstW; + int dstH = c->dstH; + int ret; + av_log(c, AV_LOG_VERBOSE, "YUV color matrix differs for YUV->YUV, using intermediate RGB to convert\n"); + + if (isNBPS(c->dstFormat) || is16BPS(c->dstFormat)) { + if (isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) { + tmp_format = AV_PIX_FMT_BGRA64; + } else { + tmp_format = AV_PIX_FMT_BGR48; + } + } else { + if (isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) { + tmp_format = AV_PIX_FMT_BGRA; + } else { + tmp_format = AV_PIX_FMT_BGR24; + } + } + + if (srcW*srcH > dstW*dstH) { + tmp_width = dstW; + tmp_height = dstH; + } else { + tmp_width = srcW; + tmp_height = srcH; + } + + ret = av_image_alloc(c->cascaded_tmp, c->cascaded_tmpStride, + tmp_width, tmp_height, tmp_format, 64); + if (ret < 0) + return ret; + + c->cascaded_context[0] = sws_alloc_set_opts(srcW, srcH, c->srcFormat, + tmp_width, tmp_height, tmp_format, + c->flags, c->param); + if (!c->cascaded_context[0]) + return -1; + + c->cascaded_context[0]->alphablend = c->alphablend; + ret = sws_init_context(c->cascaded_context[0], NULL , NULL); + if (ret < 0) + return ret; + //we set both src and dst depending on that the RGB side will be ignored + sws_setColorspaceDetails(c->cascaded_context[0], inv_table, + srcRange, table, dstRange, + brightness, contrast, saturation); + + c->cascaded_context[1] = sws_getContext(tmp_width, tmp_height, tmp_format, + dstW, dstH, c->dstFormat, + c->flags, NULL, NULL, c->param); + if (!c->cascaded_context[1]) + return -1; + sws_setColorspaceDetails(c->cascaded_context[1], inv_table, + srcRange, table, dstRange, + 0, 1 << 16, 1 << 16); + return 0; + } return -1; + } c->dstFormatBpp = av_get_bits_per_pixel(desc_dst); c->srcFormatBpp = av_get_bits_per_pixel(desc_src); -- cgit v1.2.3