History

avfilter/vf_libplacebo: skip rendering fully invisible planes

Sometimes, one input fully obscures another. In this case, we can skip actually rendering any input below the obscuring one. The reason I don't simply start the main render loop at `idx_start` will become apparent in the following commit. We can't use pl_frame_is_cropped() on this dummy frame, but we need to determine the reference frame before we can map the real output, so to resolve this conflict, we just reimplement the crop detection logic using the output link dimensions.

Niklas Haas committed 1 year ago

Commit 3091bca1 parent 6627c8e1 file · +35 −3Browse files

Unified · Split

libavfilter/vf_libplacebo.c+35−3
@@ -16,6 +16,8 @@ · 15 unmodified lines
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */17 */
18 18
19#include <math.h>
20
19#include "libavutil/avassert.h"21#include "libavutil/avassert.h"
20#include "libavutil/eval.h"22#include "libavutil/eval.h"
21#include "libavutil/fifo.h"23#include "libavutil/fifo.h"
@@ -913,10 +915,39 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) · 891 unmodified lines
913 pl_options opts = s->opts;915 pl_options opts = s->opts;
914 AVFilterLink *outlink = ctx->outputs[0];916 AVFilterLink *outlink = ctx->outputs[0];
915 const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);917 const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
918 const double target_pts = pts * av_q2d(outlink->time_base);
916 struct pl_frame target;919 struct pl_frame target;
917 const AVFrame *ref = NULL;920 const AVFrame *ref = NULL;
918 AVFrame *out;921 AVFrame *out;
919 922
923 /* Count the number of visible inputs, by excluding frames which are fully
924 * obscured or which have no frames in the mix */
925 int idx_start = 0, nb_visible = 0;
926 for (int i = 0; i < s->nb_inputs; i++) {
927 LibplaceboInput *in = &s->inputs[i];
928 struct pl_frame dummy;
929 if (in->qstatus != PL_QUEUE_OK || !in->mix.num_frames)
930 continue;
931 const struct pl_frame *cur = pl_frame_mix_current(&in->mix);
932 update_crops(ctx, in, &dummy, target_pts);
933 const int x0 = roundf(FFMIN(dummy.crop.x0, dummy.crop.x1)),
934 y0 = roundf(FFMIN(dummy.crop.y0, dummy.crop.y1)),
935 x1 = roundf(FFMAX(dummy.crop.x0, dummy.crop.x1)),
936 y1 = roundf(FFMAX(dummy.crop.y0, dummy.crop.y1));
937
938 /* If an opaque frame covers entire the output, disregard all lower layers */
939 const bool cropped = x0 > 0 || y0 > 0 || x1 < outlink->w || y1 < outlink->h;
940 if (!cropped && cur->repr.alpha == PL_ALPHA_NONE) {
941 idx_start = i;
942 nb_visible = 0;
943 }
944 nb_visible++;
945 }
946
947 /* It should be impossible to call output_frame() without at least one
948 * valid nonempty frame mix */
949 av_assert1(nb_visible > 0);
950
920 /* Use the first active input as metadata reference */951 /* Use the first active input as metadata reference */
921 for (int i = 0; i < s->nb_inputs; i++) {952 for (int i = 0; i < s->nb_inputs; i++) {
922 const LibplaceboInput *in = &s->inputs[i];953 const LibplaceboInput *in = &s->inputs[i];
@@ -989,7 +1020,8 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) · 66 unmodified lines
989 1020
990 struct pl_frame orig_target = target;1021 struct pl_frame orig_target = target;
991 bool use_linear_compositor = false;1022 bool use_linear_compositor = false;
992 if (s->linear_tex && target.color.transfer != PL_COLOR_TRC_LINEAR && !s->disable_linear) {1023 if (s->linear_tex && target.color.transfer != PL_COLOR_TRC_LINEAR &&
1024 !s->disable_linear && nb_visible > 1) {
993 target = (struct pl_frame) {1025 target = (struct pl_frame) {
994 .num_planes = 1,1026 .num_planes = 1,
995 .planes[0] = {1027 .planes[0] = {
@@ -1017,10 +1049,10 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) · 21 unmodified lines
1017 FilterLink *il = ff_filter_link(ctx->inputs[i]);1049 FilterLink *il = ff_filter_link(ctx->inputs[i]);
1018 FilterLink *ol = ff_filter_link(outlink);1050 FilterLink *ol = ff_filter_link(outlink);
1019 int high_fps = av_cmp_q(il->frame_rate, ol->frame_rate) >= 0;1051 int high_fps = av_cmp_q(il->frame_rate, ol->frame_rate) >= 0;
1020 if (in->qstatus != PL_QUEUE_OK || !in->mix.num_frames)1052 if (in->qstatus != PL_QUEUE_OK || !in->mix.num_frames || i < idx_start)
1021 continue;1053 continue;
1022 opts->params.skip_caching_single_frame = high_fps;1054 opts->params.skip_caching_single_frame = high_fps;
1023 update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base));1055 update_crops(ctx, in, &target, target_pts);
1024 pl_render_image_mix(in->renderer, &in->mix, &target, &opts->params);1056 pl_render_image_mix(in->renderer, &in->mix, &target, &opts->params);
1025 1057
1026 /* Force straight output and set correct blend mode */1058 /* Force straight output and set correct blend mode */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t