Skip to content

Conversation

@sethvincent
Copy link
Contributor

This adds metadata and sidedata apis to the Frame class and adds options helpers to FilterContext.

@sethvincent sethvincent requested a review from a team October 28, 2025 00:14
Comment on lines +9 to +41
getOption(name, flags = optionFlags.SEARCH_CHILDREN) {
return binding.getOption(this._handle, name, flags)
}

setOption(name, value, flags = optionFlags.SEARCH_CHILDREN) {
binding.setOption(this._handle, name, value, flags)
}

setOptionDictionary(dictionary, flags = optionFlags.SEARCH_CHILDREN) {
binding.setOptionDictionary(this._handle, dictionary._handle, flags)
}

setOptionDefaults() {
binding.setOptionDefaults(this._handle)
}

listOptionNames(flags = optionFlags.SEARCH_CHILDREN) {
return binding.listOptionNames(this._handle, flags)
}

getOptions(flags = optionFlags.SEARCH_CHILDREN) {
const options = {}

for (const name of this.listOptionNames(flags)) {
try {
options[name] = this.getOption(name, flags)
} catch (error) {
// Non-string options are currently ignored to match CodecContext behaviour.
}
}

return options
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is time for having a class we could compose with?


class FrameMetadata {
constructor(frame) {
this._frame = frame
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we only use the frame I would do this:

Suggested change
this._frame = frame
this._frameHandle = frame._handle

Comment on lines +158 to +161
get sideData() {
const handles = binding.getFrameSideData(this._handle)
return handles.map((handle) => new FrameSideData(handle))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I rethink about it, It looks like we repeat a lot of code with PacketSideData.

Maybe we should open an issue and discuss how we could generalise with a SideData abstract instead of the dupe PacketSideData/FrameSideData

t.ok(filterCtx)
})

test('FilterContext exposes runtime option helpers', (t) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would split the test into two different scenarios. In the first one we assert that get returns something and its type (or that it is the same than default) and in the second we assert the set logic.

In case of regression we could see which part is failing.

Comment on lines +139 to +143
const frame = new ffmpeg.Frame()

const payload = Buffer.from(
Array.from({ length: 32 }, (_, index) => (index * 7) & 0xff)
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const frame = new ffmpeg.Frame()
const payload = Buffer.from(
Array.from({ length: 32 }, (_, index) => (index * 7) & 0xff)
)
const frame = new ffmpeg.Frame()
const payload = Buffer.from(
Array.from({ length: 32 }, (_, index) => (index * 7) & 0xff)
)

Comment on lines +157 to +158
frame.removeSideData(ffmpeg.constants.frameSideDataType.CONTENT_LIGHT_LEVEL)
t.is(frame.sideData.length, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would test that separately.

Comment on lines +166 to +169
const inputFrame = createAudioFrame(0)
t.teardown(() => {
inputFrame.destroy()
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using could work here.

Comment on lines +180 to +188
const entries = outputFrame.metadata.entries()
t.ok(entries.length > 0)

const astatsEntry = entries.find(([key]) => key.startsWith('lavfi.astats.'))
t.ok(astatsEntry)

const [key, value] = astatsEntry
t.is(outputFrame.metadata.get(key), value)
t.is(outputFrame.metadata.get('missing-key'), null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sound like we asserting distincts things, maybe could we put it into different scenarios.

@sethvincent
Copy link
Contributor Author

@tony-go Yeah, both the FrameSideData class and the FilterContext options api are duplicating other code at the moment.

Should we fix that in this pull request?

I was thinking of doing that if/when a third instance of the code is imminent, but it could be done now.

I'll look at what else has a side data api and options api.

@tony-go
Copy link
Contributor

tony-go commented Oct 29, 2025

Should we fix that in this pull request?

@sethvincent As I said here #173 (comment)

Maybe we should open an issue and discuss how we could generalise with a SideData abstract instead of the dupe PacketSideData/FrameSideData

We could simply open an issue.

sethvincent and others added 2 commits November 10, 2025 15:09
Co-authored-by: Tony Gorez <gorez.tony@gmail.com>
Co-authored-by: Tony Gorez <gorez.tony@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants