diff --git a/vhook/watermark.c b/vhook/watermark.c index 5b113a476261ef25b2e487f200bd5df97e11cbb2..522c5e058cc813fbef9c1ac8aba6f6cdcea0ea9f 100644 --- a/vhook/watermark.c +++ b/vhook/watermark.c @@ -63,6 +63,9 @@ #include "framehook.h" #include "cmdutils.h" +#include "swscale.h" + +static int sws_flags = SWS_BICUBIC; typedef struct { char filename[2000]; @@ -89,6 +92,13 @@ typedef struct { int thrG; int thrB; int mode; + + // This vhook first converts frame to RGB ... + struct SwsContext *toRGB_convert_ctx; + // ... then converts a watermark and applies it to the RGB frame ... + struct SwsContext *watermark_convert_ctx; + // ... and finally converts back frame from RGB to initial format + struct SwsContext *fromRGB_convert_ctx; } ContextInfo; int get_watermark_picture(ContextInfo *ci, int cleanup); @@ -102,8 +112,12 @@ void Release(void *ctx) ContextInfo *ci; ci = (ContextInfo *) ctx; - if (ci) get_watermark_picture(ci, 1); - + if (ci) { + get_watermark_picture(ci, 1); + sws_freeContext(ci->toRGB_convert_ctx); + sws_freeContext(ci->watermark_convert_ctx); + sws_freeContext(ci->fromRGB_convert_ctx); + } av_free(ctx); } @@ -201,11 +215,24 @@ static void Process0(void *ctx, buf = av_malloc(size); avpicture_fill(&picture1, buf, PIX_FMT_RGBA32, src_width, src_height); - if (img_convert(&picture1, PIX_FMT_RGBA32, - picture, pix_fmt, src_width, src_height) < 0) { - av_free(buf); - return; + + // if we already got a SWS context, let's realloc if is not re-useable + ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, + src_width, src_height, pix_fmt, + src_width, src_height, PIX_FMT_RGBA32, + 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); } + +// 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, src_height, + picture1.data, picture1.linesize); + pict = &picture1; } @@ -265,9 +292,20 @@ static void Process0(void *ctx, if (pix_fmt != PIX_FMT_RGBA32) { - if (img_convert(picture, pix_fmt, - &picture1, PIX_FMT_RGBA32, src_width, src_height) < 0) { + ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx, + src_width, src_height, PIX_FMT_RGBA32, + src_width, src_height, 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->fromRGB_convert_ctx, + picture1.data, picture1.linesize, 0, src_height, + picture->data, picture->linesize); } av_free(buf); @@ -308,11 +346,24 @@ static void Process1(void *ctx, buf = av_malloc(size); avpicture_fill(&picture1, buf, PIX_FMT_RGBA32, src_width, src_height); - if (img_convert(&picture1, PIX_FMT_RGBA32, - picture, pix_fmt, src_width, src_height) < 0) { - av_free(buf); - return; + + // if we already got a SWS context, let's realloc if is not re-useable + ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx, + src_width, src_height, pix_fmt, + src_width, src_height, PIX_FMT_RGBA32, + 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); } + +// 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, src_height, + picture1.data, picture1.linesize); + pict = &picture1; } @@ -352,9 +403,20 @@ static void Process1(void *ctx, } // foreach Y if (pix_fmt != PIX_FMT_RGBA32) { - if (img_convert(picture, pix_fmt, - &picture1, PIX_FMT_RGBA32, src_width, src_height) < 0) { + ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx, + src_width, src_height, PIX_FMT_RGBA32, + src_width, src_height, 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->fromRGB_convert_ctx, + picture1.data, picture1.linesize, 0, src_height, + picture->data, picture->linesize); } av_free(buf); @@ -540,9 +602,21 @@ int get_watermark_picture(ContextInfo *ci, int cleanup) if(ci->frameFinished) { // Convert the image from its native format to RGBA32 - img_convert((AVPicture *)ci->pFrameRGB, PIX_FMT_RGBA32, - (AVPicture*)(ci->pFrame), ci->pCodecCtx->pix_fmt, ci->pCodecCtx->width, - ci->pCodecCtx->height); + ci->watermark_convert_ctx = + sws_getCachedContext(ci->watermark_convert_ctx, + ci->pCodecCtx->width, ci->pCodecCtx->height, ci->pCodecCtx->pix_fmt, + ci->pCodecCtx->width, ci->pCodecCtx->height, PIX_FMT_RGBA32, + sws_flags, NULL, NULL, NULL); + if (ci->watermark_convert_ctx == NULL) { + av_log(NULL, AV_LOG_ERROR, + "Cannot initialize the watermark 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->watermark_convert_ctx, + ci->pFrame->data, ci->pFrame->linesize, 0, ci->pCodecCtx->height, + ci->pFrameRGB->data, ci->pFrameRGB->linesize); // Process the video frame (save to disk etc.) //fprintf(stderr,"banan() New frame!\n");