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
1616 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717 */
1818
19+#include <math.h>
20+
1921 #include "libavutil/avassert.h"
2022 #include "libavutil/eval.h"
2123 #include "libavutil/fifo.h"
@@ -913,10 +915,39 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) · 891 unmodified lines
913915 pl_options opts = s->opts;
914916 AVFilterLink *outlink = ctx->outputs[0];
915917 const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
918+ const double target_pts = pts * av_q2d(outlink->time_base);
916919 struct pl_frame target;
917920 const AVFrame *ref = NULL;
918921 AVFrame *out;
919922
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+
920951 /* Use the first active input as metadata reference */
921952 for (int i = 0; i < s->nb_inputs; i++) {
922953 const LibplaceboInput *in = &s->inputs[i];
@@ -989,7 +1020,8 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) · 66 unmodified lines
9891020
9901021 struct pl_frame orig_target = target;
9911022 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) {
9931025 target = (struct pl_frame) {
9941026 .num_planes = 1,
9951027 .planes[0] = {
@@ -1017,10 +1049,10 @@ static int output_frame(AVFilterContext *ctx, int64_t pts) · 21 unmodified lines
10171049 FilterLink *il = ff_filter_link(ctx->inputs[i]);
10181050 FilterLink *ol = ff_filter_link(outlink);
10191051 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)
10211053 continue;
10221054 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);
10241056 pl_render_image_mix(in->renderer, &in->mix, &target, &opts->params);
10251057
10261058 /* 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