diff --git a/vhook/null.c b/vhook/null.c index 1507d677c3..ff822037e6 100644 --- a/vhook/null.c +++ b/vhook/null.c @@ -19,9 +19,24 @@ #include #include "framehook.h" +#include "swscale.h" + +static int sws_flags = SWS_BICUBIC; typedef struct { int dummy; + + // This vhook first converts frame to RGB ... + struct SwsContext *toRGB_convert_ctx; + + // ... and later converts back frame from RGB to initial format + struct SwsContext *fromRGB_convert_ctx; + + enum PixelFormat sws_pix_fmt; // Sws_Context is opaque, we need to save + int sws_width, sws_height; // this to check if we can re-use contexts + // Contexts will be re-used 99% of time, + // I know of width/height changes only in DVB broadcasts + } ContextInfo; void Release(void *ctx) @@ -29,8 +44,11 @@ void Release(void *ctx) ContextInfo *ci; ci = (ContextInfo *) ctx; - if (ctx) + if (ctx) { + sws_freeContext(ci->toRGB_convert_ctx); + sws_freeContext(ci->fromRGB_convert_ctx); av_free(ctx); + } } int Configure(void **ctxp, int argc, char *argv[]) @@ -57,20 +75,59 @@ void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, buf = av_malloc(size); avpicture_fill(&picture1, buf, PIX_FMT_RGB24, width, height); - if (img_convert(&picture1, PIX_FMT_RGB24, - picture, pix_fmt, width, height) < 0) { - av_free(buf); - return; + + // if we already got a SWS context, let's realloc if is not re-useable + if (ci->toRGB_convert_ctx != NULL) { + if ((ci->sws_pix_fmt != pix_fmt) || + (ci->sws_width != width) || (ci->sws_height != height)) { + sws_freeContext(ci->toRGB_convert_ctx); + ci->toRGB_convert_ctx = NULL; + sws_freeContext(ci->fromRGB_convert_ctx); + ci->fromRGB_convert_ctx = NULL; + } } + if (ci->toRGB_convert_ctx == NULL) { + ci->sws_pix_fmt = pix_fmt; + ci->sws_width = width; + ci->sws_height = height; + ci->toRGB_convert_ctx = sws_getContext( + ci->sws_width, ci->sws_height, + ci->sws_pix_fmt, + ci->sws_width, ci->sws_height, + PIX_FMT_RGB24, + sws_flags, NULL, NULL, NULL); + if (ci->toRGB_convert_ctx == NULL) { + av_log(NULL, AV_LOG_ERROR, + "Cannot initialize the toRGB conversion context\n"); + exit(1); + } + ci->fromRGB_convert_ctx = sws_getContext( + ci->sws_width, ci->sws_height, + PIX_FMT_RGB24, + ci->sws_width, ci->sws_height, + ci->sws_pix_fmt, + sws_flags, NULL, NULL, NULL); + if (ci->fromRGB_convert_ctx == NULL) { + av_log(NULL, AV_LOG_ERROR, + "Cannot initialize the fromRGB conversion context\n"); + exit(1); + } + } +// img_convert parameters are 2 first destination, then 4 source +// sws_scale parameters are context, 4 first source, then 2 destination + sws_scale(ci->toRGB_convert_ctx, + picture->data, picture->linesize, 0, ci->sws_height, + picture1.data, picture1.linesize); + pict = &picture1; } /* Insert filter code here */ if (pix_fmt != PIX_FMT_RGB24) { - if (img_convert(picture, pix_fmt, - &picture1, PIX_FMT_RGB24, width, height) < 0) { - } + sws_scale(ci->fromRGB_convert_ctx, + picture1.data, picture1.linesize, 0, ci->sws_height, + picture->data, picture->linesize); } av_free(buf);