From 4c2e430c0cfedc0d22047da566fe59a2d36ef58a Mon Sep 17 00:00:00 2001 From: jpark37 Date: Thu, 30 Apr 2020 11:48:39 -0700 Subject: [PATCH 1/3] libobs: Fix right edge for JPEG images FFmpeg YUV to RGB conversions require extra destination padding. --- libobs/graphics/graphics-ffmpeg.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/libobs/graphics/graphics-ffmpeg.c b/libobs/graphics/graphics-ffmpeg.c index 5b2e0fb48..eb2467ecc 100644 --- a/libobs/graphics/graphics-ffmpeg.c +++ b/libobs/graphics/graphics-ffmpeg.c @@ -2,6 +2,7 @@ #include #include +#include #include #include "../obs-ffmpeg-compat.h" @@ -122,9 +123,11 @@ static bool ffmpeg_image_reformat_frame(struct ffmpeg_image *info, } } else { + static const enum AVPixelFormat format = AV_PIX_FMT_BGRA; + sws_ctx = sws_getContext(info->cx, info->cy, info->format, - info->cx, info->cy, AV_PIX_FMT_BGRA, - SWS_POINT, NULL, NULL, NULL); + info->cx, info->cy, format, SWS_POINT, + NULL, NULL, NULL); if (!sws_ctx) { blog(LOG_WARNING, "Failed to create scale context " @@ -133,17 +136,36 @@ static bool ffmpeg_image_reformat_frame(struct ffmpeg_image *info, return false; } + uint8_t *pointers[4]; + int linesizes[4]; + ret = av_image_alloc(pointers, linesizes, info->cx, info->cy, + format, 32); + if (ret < 0) { + blog(LOG_WARNING, "av_image_alloc failed for '%s': %s", + info->file, av_err2str(ret)); + sws_freeContext(sws_ctx); + return false; + } + ret = sws_scale(sws_ctx, (const uint8_t *const *)frame->data, - frame->linesize, 0, info->cy, &out, &linesize); + frame->linesize, 0, info->cy, pointers, + linesizes); sws_freeContext(sws_ctx); if (ret < 0) { blog(LOG_WARNING, "sws_scale failed for '%s': %s", info->file, av_err2str(ret)); + av_freep(pointers); return false; } - info->format = AV_PIX_FMT_BGRA; + for (size_t y = 0; y < (size_t)info->cy; y++) + memcpy(out + y * linesize, + pointers[0] + y * linesizes[0], linesize); + + av_freep(pointers); + + info->format = format; } return true; From 2123b306f38184ab7291d760328b64182da9864f Mon Sep 17 00:00:00 2001 From: jpark37 Date: Thu, 30 Apr 2020 11:51:11 -0700 Subject: [PATCH 2/3] libobs: Fix right edge of some videos FFmpeg YUV to RGB conversions require extra destination padding. The Mantis issue might have been fixed when some YUV format conversions were moved to the GPU, but this may fix other YUV formats. Fixes https://obsproject.com/mantis/view.php?id=1177 --- deps/media-playback/media-playback/media.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/media-playback/media-playback/media.c b/deps/media-playback/media-playback/media.c index 3beaa0cf1..dc8558da8 100644 --- a/deps/media-playback/media-playback/media.c +++ b/deps/media-playback/media-playback/media.c @@ -216,7 +216,7 @@ static bool mp_media_init_scaling(mp_media_t *m) int ret = av_image_alloc(m->scale_pic, m->scale_linesizes, m->v.decoder->width, m->v.decoder->height, - m->scale_format, 1); + m->scale_format, 32); if (ret < 0) { blog(LOG_WARNING, "MP: Failed to create scale pic data"); return false; From d9fa5de5724373d3b13cae713b15ccd889cdd958 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Thu, 30 Apr 2020 12:01:16 -0700 Subject: [PATCH 3/3] libobs: Fix right edge for "video scaler" FFmpeg YUV to RGB conversions require extra destination padding. This code only appears to be exercised for DeckLink. --- libobs/media-io/video-scaler-ffmpeg.c | 45 +++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/libobs/media-io/video-scaler-ffmpeg.c b/libobs/media-io/video-scaler-ffmpeg.c index 493b7aa37..e113b650c 100644 --- a/libobs/media-io/video-scaler-ffmpeg.c +++ b/libobs/media-io/video-scaler-ffmpeg.c @@ -18,11 +18,15 @@ #include "../util/bmem.h" #include "video-scaler.h" +#include #include struct video_scaler { struct SwsContext *swscale; int src_height; + int dst_height; + uint8_t *dst_pointers[4]; + int dst_linesizes[4]; }; static inline enum AVPixelFormat @@ -138,6 +142,15 @@ int video_scaler_create(video_scaler_t **scaler_out, scaler = bzalloc(sizeof(struct video_scaler)); scaler->src_height = src->height; + scaler->dst_height = dst->height; + + ret = av_image_alloc(scaler->dst_pointers, scaler->dst_linesizes, + dst->width, dst->height, format_dst, 32); + if (ret < 0) { + blog(LOG_WARNING, + "video_scaler_create: av_image_alloc failed: %d", ret); + goto fail; + } scaler->swscale = sws_getCachedContext(NULL, src->width, src->height, format_src, dst->width, @@ -169,6 +182,10 @@ void video_scaler_destroy(video_scaler_t *scaler) { if (scaler) { sws_freeContext(scaler->swscale); + + if (scaler->dst_pointers[0]) + av_freep(scaler->dst_pointers); + bfree(scaler); } } @@ -182,13 +199,37 @@ bool video_scaler_scale(video_scaler_t *scaler, uint8_t *output[], return false; int ret = sws_scale(scaler->swscale, input, (const int *)in_linesize, 0, - scaler->src_height, output, - (const int *)out_linesize); + scaler->src_height, scaler->dst_pointers, + scaler->dst_linesizes); if (ret <= 0) { blog(LOG_ERROR, "video_scaler_scale: sws_scale failed: %d", ret); return false; } + const size_t height = scaler->dst_height; + for (size_t plane = 0; plane < 4; ++plane) { + if (!scaler->dst_pointers[plane]) + continue; + + const size_t scaled_linesize = scaler->dst_linesizes[plane]; + const size_t plane_linesize = out_linesize[plane]; + uint8_t *dst = output[plane]; + const uint8_t *src = scaler->dst_pointers[plane]; + if (scaled_linesize == plane_linesize) { + memcpy(dst, src, scaled_linesize * height); + } else { + size_t linesize = scaled_linesize; + if (linesize > plane_linesize) + linesize = plane_linesize; + + for (size_t y = 0; y < height; y++) { + memcpy(dst, src, linesize); + dst += plane_linesize; + src += scaled_linesize; + } + } + } + return true; }