Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Buffer Expansion - SmartFX

Community Beginner ,
Jun 10, 2025 Jun 10, 2025

So I modified the Skeleton sample plugin by adding SmartFX and by making it move the layer based on 2 parameters, X and Y, because I want to understand how to make it go out of bounds.

 

If I set the rects like this:

extra->output->result_rect = in_result.result_rect;
extra->output->max_result_rect = expanded_rect;

Then the expansion is not happening or whatever, because the pixels are clearly still limited by the bounds.

If I set them like this:

extra->output->result_rect = expanded_rect;
extra->output->max_result_rect = expanded_rect;

 

Then the effect just gets completely bugged and moves the layer to top-left.

 

What am I missing? I tried so many things...such a sad thing that we don't have a sample plugin in the SDK that shows how to do this.

 

Here's my currect PreRender btw:

static PF_Err
PreRender(
	PF_InData* in_data,
	PF_OutData* out_data,
	PF_PreRenderExtra* extra)
{
	PF_Err err = PF_Err_NONE;
	PF_RenderRequest req = extra->input->output_request;
	PF_CheckoutResult in_result;

	ERR(extra->cb->checkout_layer(in_data->effect_ref,
		SKELETON_INPUT,
		SKELETON_INPUT,
		&req,
		in_data->current_time,
		in_data->time_step,
		in_data->time_scale,
		&in_result));


	PF_LRect expanded_rect = in_result.result_rect;
	expanded_rect.left -= 200;
	expanded_rect.top -= 200;
	expanded_rect.right += 200;
	expanded_rect.bottom += 200;

	extra->output->result_rect = in_result.result_rect;
	extra->output->max_result_rect = expanded_rect;

	extra->output->flags |= PF_RenderOutputFlag_RETURNS_EXTRA_PIXELS;

	return err;
}
TOPICS
How to , SDK
354
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Jun 10, 2025 Jun 10, 2025

HI DKT,

Thanks for the question. I appreciate you labeling the post as SDK. It's a bit out of my purview to field this qustion, but I did want to acknowledge and thank you for posting. Hopefully, the product team or the community will respond shortly. Sorry for the frustration.

 

Take Care,

Kevin

Kevin Monahan - Sr. Community & Engagement Strategist – Pro Video and Audio
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jun 10, 2025 Jun 10, 2025

To ensure it's working correctly, you need to account for the difference in origins in smart_render. When you expand the output, it's now larger than the input:

PF_Rect dstRect = { input_world->origin_x - output_world->origin_x, 
                    input_world->origin_y - output_world->origin_y, 
                    0, 0 };

dstRect.right = dstRect.left + input_world->width;
dstRect.bottom = dstRect.top + input_world->height;

PF_COPY(input_world, output_world, NULL, &dstRect);

 An even easier way to verify if your output buffer is expanding correctly is simply to fill it with a solid colour.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 11, 2025 Jun 11, 2025

That would work if the only thing you wanna do is fill the buffer with a color. What do you do if your plugin moves the layer, or samples? I modified the skeleton to move the layer via sampling. Custom SampleBilinear function and custom offset function. Nothing I do is working, the layer is just completely bugged when I try to expand the buffer.

 

What you provided there just copies the pixels in the center of the buffer, that's not really helpful in my situation.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jun 11, 2025 Jun 11, 2025

If you want to transform the layer, you start with an identity matrix, add your other transforms, and feed it into transform_world. You still need to account for the origin difference, otherwise it will be at the top left of your output buffer. I think your pre_render code is correct, and you can verify it is using the methods i mentioned in my previous reply. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 11, 2025 Jun 11, 2025

Ok, now the layer doesn't move to top-left, but the bottom-right part gets clipped.image_2025-06-11_222258322.png

Is this not correct?

static PF_Err
SmartRender(
	PF_InData* in_data,
	PF_OutData* out_data,
	PF_SmartRenderExtra* extra)
{
	PF_Err err = PF_Err_NONE;
	AEGP_SuiteHandler suites(in_data->pica_basicP);

	PF_EffectWorld* input_worldP = NULL;
	PF_EffectWorld* output_worldP = NULL;

	ERR(extra->cb->checkout_layer_pixels(in_data->effect_ref, SKELETON_INPUT, &input_worldP));

	if (!err) {
		ERR(extra->cb->checkout_output(in_data->effect_ref, &output_worldP));

		if (!err && input_worldP && output_worldP) {
			PF_ParamDef x_param, y_param;
			AEFX_CLR_STRUCT(x_param);
			AEFX_CLR_STRUCT(y_param);

			ERR(PF_CHECKOUT_PARAM(in_data, SKELETON_X, in_data->current_time, in_data->time_step, in_data->time_scale, &x_param));
			ERR(PF_CHECKOUT_PARAM(in_data, SKELETON_Y, in_data->current_time, in_data->time_step, in_data->time_scale, &y_param));

			if (!err) {
				A_long origin_x_offset = input_worldP->origin_x - output_worldP->origin_x;
				A_long origin_y_offset = input_worldP->origin_y - output_worldP->origin_y;

				OffsetInfo offsetInfo;
				offsetInfo.xOffset = x_param.u.fs_d.value + origin_x_offset;
				offsetInfo.yOffset = y_param.u.fs_d.value + origin_y_offset;
				offsetInfo.input_world = input_worldP;

				PF_PixelFormat pixelFormat;
				PF_WorldSuite2* wsP = NULL;
				ERR(suites.Pica()->AcquireSuite(kPFWorldSuite, kPFWorldSuiteVersion2, (const void**)&wsP));
				ERR(wsP->PF_GetPixelFormat(output_worldP, &pixelFormat));
				ERR(suites.Pica()->ReleaseSuite(kPFWorldSuite, kPFWorldSuiteVersion2));

				switch (pixelFormat) {
				case PF_PixelFormat_ARGB128:
					ERR(suites.IterateFloatSuite1()->iterate(
						in_data,
						0,
						output_worldP->height,
						input_worldP,
						NULL,
						(void*)&offsetInfo,
						(PF_IteratePixelFloatFunc)MyOffsetFunc<PF_PixelFloat>,
						output_worldP));
					break;

				case PF_PixelFormat_ARGB64:
					ERR(suites.Iterate16Suite1()->iterate(
						in_data,
						0,
						output_worldP->height,
						input_worldP,
						NULL,
						(void*)&offsetInfo,
						MyOffsetFunc<PF_Pixel16>,
						output_worldP));
					break;

				case PF_PixelFormat_ARGB32:
				default:
					ERR(suites.Iterate8Suite1()->iterate(
						in_data,
						0,
						output_worldP->height,
						input_worldP,
						NULL,
						(void*)&offsetInfo,
						MyOffsetFunc<PF_Pixel8>,
						output_worldP));
					break;
				}

				PF_CHECKIN_PARAM(in_data, &x_param);
				PF_CHECKIN_PARAM(in_data, &y_param);
			}
		}
	}

	if (input_worldP) {
		ERR(extra->cb->checkin_layer_pixels(in_data->effect_ref, SKELETON_INPUT));
	}

	return err;
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 15, 2025 Jun 15, 2025

hello? I still need help with this, it does not work...

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 15, 2025 Jun 15, 2025
LATEST

so...

i put together a working sample the shows buffer resizing in smartFX. (based on the "smarty pants" sample)

download it from here:
https://drive.google.com/file/d/1w4Fc9rtGXjU-YT4CC-6q01ft2MOvOLtt/view?usp=sharing

from what i gathered during the making of this was that you should put the expanded buffer rect in "extra->output->result_rect".

seems AE will take just that rect. i didn't see AE asking for the max_result_rect yet...

 

so depending on your implementation, you should decide *what* get's expanded.

is it relative to any buffer you get, be it cropped by a mask or the comp bounds?
is it relative to the original layer size?
is it relative to the max rect of the input?

all these very much depend on your implementation.

in the sample project, i expanded the input buffer whatever it may be, and put it in the "extra->output->result_rect". then i expanded the "in_result.max_result_rect" and put the expanded result in "

extra->output->max_result_rect".

from all i've seen, AE always used the rect from "extra->output->result_rect" for the render call, even when the layer was scaled down and exposed the area around the original layer that it *could* grow into.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines