fix: ensure vaapi hardware pad filters appropriately set frame data location

This commit is contained in:
Christian Benincasa
2026-03-28 14:11:29 -04:00
parent fcfa537279
commit 12abc265a9
3 changed files with 39 additions and 16 deletions

View File

@@ -8,17 +8,16 @@ export class PadOpenclFilter extends FilterOption {
private preprocessFilters: FilterOption[] = [];
constructor(
private currentState: FrameState,
currentState: FrameState,
private paddedSize: FrameSize,
) {
super();
if (currentState.frameDataLocation === FrameDataLocation.Software) {
this.preprocessFilters.push(new HardwareUploadVaapiFilter(true));
}
}
get filter(): string {
if (this.currentState.frameDataLocation === FrameDataLocation.Software) {
this.preprocessFilters.push(new HardwareUploadVaapiFilter(true));
}
const pad = `hwmap=derive_device=opencl,pad_opencl=w=${this.paddedSize.width}:h=${this.paddedSize.height}:x=-1:y=-1:color=black`;
return this.preprocessFilters
@@ -34,6 +33,7 @@ export class PadOpenclFilter extends FilterOption {
);
return currentState.update({
paddedSize: this.paddedSize,
frameDataLocation: FrameDataLocation.Hardware,
});
}

View File

@@ -8,17 +8,16 @@ export class PadVaapiFilter extends FilterOption {
private preprocessFilters: FilterOption[] = [];
constructor(
private currentState: FrameState,
currentState: FrameState,
private paddedSize: FrameSize,
) {
super();
if (currentState.frameDataLocation === FrameDataLocation.Software) {
this.preprocessFilters.push(new HardwareUploadVaapiFilter(true));
}
}
get filter(): string {
if (this.currentState.frameDataLocation === FrameDataLocation.Software) {
this.preprocessFilters.push(new HardwareUploadVaapiFilter(true));
}
const pad = `pad_vaapi=w=${this.paddedSize.width}:h=${this.paddedSize.height}:x=-1:y=-1:color=black`;
return this.preprocessFilters
@@ -34,6 +33,7 @@ export class PadVaapiFilter extends FilterOption {
);
return currentState.update({
paddedSize: this.paddedSize,
frameDataLocation: FrameDataLocation.Hardware,
});
}

View File

@@ -791,8 +791,19 @@ describe('VaapiPipelineBuilder pad', () => {
}),
});
const args = pipeline.getCommandArgs();
console.log(args.join(' '));
const args = pipeline.getCommandArgs().join(' ');
// pad_vaapi must be present
expect(args).toContain('pad_vaapi');
// hwdownload must appear after pad_vaapi (before the software overlay)
expect(args).toContain('hwdownload');
const padIdx = args.indexOf('pad_vaapi');
const dlIdx = args.indexOf('hwdownload');
expect(dlIdx).toBeGreaterThan(padIdx);
// any second hwupload (to re-enter hw for encoding) must come AFTER hwdownload
const secondHwuploadIdx = args.indexOf('hwupload', dlIdx);
if (secondHwuploadIdx !== -1) {
expect(secondHwuploadIdx).toBeGreaterThan(dlIdx);
}
});
});
@@ -1539,13 +1550,22 @@ describe('VaapiPipelineBuilder scale', () => {
deinterlace?: boolean;
}): Pipeline {
const capabilities = new VaapiHardwareCapabilities([
new VaapiProfileEntrypoint(VaapiProfiles.H264Main, VaapiEntrypoint.Decode),
new VaapiProfileEntrypoint(VaapiProfiles.H264Main, VaapiEntrypoint.Encode),
new VaapiProfileEntrypoint(
VaapiProfiles.H264Main,
VaapiEntrypoint.Decode,
),
new VaapiProfileEntrypoint(
VaapiProfiles.H264Main,
VaapiEntrypoint.Encode,
),
new VaapiProfileEntrypoint(
VaapiProfiles.HevcMain10,
VaapiEntrypoint.Decode,
),
new VaapiProfileEntrypoint(VaapiProfiles.HevcMain, VaapiEntrypoint.Encode),
new VaapiProfileEntrypoint(
VaapiProfiles.HevcMain,
VaapiEntrypoint.Encode,
),
]);
const binaryCapabilities =
@@ -1697,7 +1717,10 @@ describe('VaapiPipelineBuilder scale', () => {
new Set(),
new Map(),
// TonemapOpencl matches default vaapiPipelineOptions.tonemapPreference='opencl'
new Set([KnownFfmpegFilters.PadVaapi, KnownFfmpegFilters.TonemapOpencl]),
new Set([
KnownFfmpegFilters.PadVaapi,
KnownFfmpegFilters.TonemapOpencl,
]),
new Set(),
),
disableHardwareDecoding: true,