Skip to content

Add output resolution support via output format struct width/height#23

Open
khamilowicz wants to merge 1 commit into
masterfrom
add-resolution
Open

Add output resolution support via output format struct width/height#23
khamilowicz wants to merge 1 commit into
masterfrom
add-resolution

Conversation

@khamilowicz

@khamilowicz khamilowicz commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Resolution is specified directly on the output format struct (e.g. %H264{width: 160, height: 90}) rather than as a separate option
  • SWScale.Converter handles scaling when non-nil dimensions are present
  • Parser-only shortcuts for H264→H264 and H265→H265 are blocked when output has non-nil dimensions, since scaling requires full decode+encode

Test plan

  • Scaling integration tests added with reference fixtures (160x90, half of 320x180 source) for software path (H264↔H264, H264↔RawVideo)
  • Fixture filenames include resolution and proper format extension
  • Run mix test to verify all integration tests pass

🤖 Generated with Claude Code

Resolution is specified directly on the output format struct (e.g.
`%H264{width: 160, height: 90}`) rather than as a separate option.
SWScale.Converter handles scaling when non-nil dimensions are present.

Parser-only shortcuts for H264→H264 and H265→H265 are blocked when
output has non-nil dimensions, since scaling requires full decode+encode.

Vulkan path uses the same SWScale-based scaling approach. Converter
no-op detection is consolidated into named defguardp helpers:
is_nv12_native/1, raw_video_passthrough/2, h26x_compatible_input/1.

Scaling integration tests added with reference fixtures (160x90, half
of the 320x180 source) for software path (H264↔H264, H264↔RawVideo).
Fixture filenames include resolution and proper format extension.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread test/integration_test.exs
end)

defp assert_or_regenerate_scaled_fixture!(actual, fixture_path) do
if System.get_env("REGEN_SCALED_FIXTURES") == "1" do

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need a separate env for that? I think it would be enough to have a single env telling whether or not to regenerate fixtures

Comment thread test/integration_test.exs
defp assert_or_regenerate_scaled_fixture!(actual, fixture_path) do
if System.get_env("REGEN_SCALED_FIXTURES") == "1" do
File.mkdir_p!(Path.dirname(fixture_path))
File.write!(fixture_path, actual)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[NIT] we silently ignore failures here

Comment thread lib/transcoder.ex
Comment on lines +214 to +222
resolution: [
spec: {pos_integer(), pos_integer()} | nil,
default: nil,
description: """
Desired output video resolution `{width, height}` applied to all outputs.

When set, overrides `width` and `height` on the resolved output stream format.
Individual outputs can override this via the per-output `resolution` pad option.
"""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am not 100% convinced we should duplicate these options both here and in def_output_pad, perhaps let's discuss it in person

Comment thread lib/transcoder.ex
defp resolve_transcoding_policy(policy, _format), do: policy

defp resolve_output_stream_format(nil, input_format), do: input_format
defp apply_resolution(%{width: _width, height: _height} = format, {width, height}),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[NIT]

Suggested change
defp apply_resolution(%{width: _width, height: _height} = format, {width, height}),
defp apply_resolution(%{width: _width, height: _height} = format, {width, height} = _desired_resolution),

Alternatively you can type spec this function and add some labels for arguments ;)

Comment thread lib/transcoder.ex

defp resolve_output_stream_format(nil, input_format) do
case input_format do
%{width: _width, height: _height} -> %{input_format | width: nil, height: nil}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why would we discard width and height from the input_format?

Comment thread lib/transcoder/video.ex
is_raw_video_format(format)

# Input format natively produces/consumes NV12 in the VK pipeline (H264 via VK decoder, or raw NV12)
defguardp is_nv12_native(format)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

how about some names like is_vk_video_friendly_format and is_x264_friendly_format ?

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.

2 participants