Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add handling multiple handle_caps callbacks #62

Merged
merged 4 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 23 additions & 25 deletions lib/membrane/compositor_element.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ defmodule Membrane.VideoCompositor.CompositorElement do
alias Membrane.RawVideo
alias Membrane.VideoCompositor.Wgpu

def_options caps: [
spec: RawVideo.t(),
description: "Struct with video width, height, framerate and pixel format."
],
real_time: [
spec: boolean(),
description: """
Set the compositor to real-time mode.
""",
default: false
]

def_input_pad :input,
def_options(
caps: [
spec: RawVideo.t(),
description: "Struct with video width, height, framerate and pixel format."
],
real_time: [
spec: boolean(),
description: """
Set the compositor to real-time mode.
""",
default: false
]
)
WojciechBarczynski marked this conversation as resolved.
Show resolved Hide resolved

def_input_pad(:input,
WojciechBarczynski marked this conversation as resolved.
Show resolved Hide resolved
demand_unit: :buffers,
availability: :on_request,
demand_mode: :auto,
Expand All @@ -45,18 +47,20 @@ defmodule Membrane.VideoCompositor.CompositorElement do
default: {0, 0}
]
]
)

def_output_pad :output,
def_output_pad(:output,
demand_unit: :buffers,
demand_mode: :auto,
caps: {RawVideo, pixel_format: :I420}
)

@impl true
def handle_init(options) do
{:ok, wgpu_state} = Wgpu.init(options.caps)

state = %{
video_positions_waiting_for_caps: %{},
videos_positions: %{},
caps: options.caps,
real_time: options.real_time,
wgpu_state: wgpu_state,
Expand Down Expand Up @@ -103,8 +107,7 @@ defmodule Membrane.VideoCompositor.CompositorElement do

%{
state
| video_positions_waiting_for_caps:
Map.put(state.video_positions_waiting_for_caps, new_id, position),
| videos_positions: Map.put(state.videos_positions, new_id, position),
pads_to_ids: Map.put(state.pads_to_ids, pad, new_id),
new_pad_id: new_id + 1
}
Expand All @@ -115,18 +118,13 @@ defmodule Membrane.VideoCompositor.CompositorElement do
%{
pads_to_ids: pads_to_ids,
wgpu_state: wgpu_state,
video_positions_waiting_for_caps: video_positions_waiting_for_caps
videos_positions: videos_positions
} = state

id = Map.get(pads_to_ids, pad)

{position, video_positions_waiting_for_caps} = Map.pop!(video_positions_waiting_for_caps, id)
:ok = Wgpu.add_video(wgpu_state, id, caps, position)

state = %{
state
| video_positions_waiting_for_caps: video_positions_waiting_for_caps
}
position = Map.get(videos_positions, id)
:ok = Wgpu.put_video(wgpu_state, id, caps, position)

{:ok, state}
end
Expand Down
8 changes: 2 additions & 6 deletions lib/membrane/video_compositor/wgpu/native.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@ defmodule Membrane.VideoCompositor.Wgpu.Native do
@spec force_render(wgpu_state()) :: {:ok, frame_with_pts()} | {:error, atom()}
def force_render(_state), do: error()

@spec add_video(wgpu_state(), id_t(), RawVideo.t(), VideoProperties.t()) ::
@spec put_video(wgpu_state(), id_t(), RawVideo.t(), VideoProperties.t()) ::
:ok | {:error, error_t()}
def add_video(_state, _id, _in_video, _properties), do: error()

@spec set_properties(wgpu_state(), id_t(), VideoProperties.t()) ::
:ok | {:error, error_t()}
def set_properties(_state, _id, _properties), do: error()
def put_video(_state, _id, _in_video, _properties), do: error()

@spec remove_video(wgpu_state(), id_t()) ::
:ok | {:error, error_t()}
Expand Down
30 changes: 5 additions & 25 deletions lib/membrane/video_compositor/wgpu/wgpu.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,53 +53,33 @@ defmodule Membrane.VideoCompositor.Wgpu do
end

@doc """
Registers a new input video with the given numerical `id`.
Set input video with the given numerical `id`.
Used for adding new input videos as well as updating properties of existing ones.

Provided `id` should be unique within all previous ones, otherwise the compositor may or may not replace
the old video with this id with a new one.
`x` and `y` are pixel coordinates specifying where the top-left corner of the video should be.
`z` must be a float between 0.0 and 1.0, and it determines which videos are drawn in front of others.
A video with a higher `z` coordinate will cover videos with lower `z` coordinates.
"""
@spec add_video(
@spec put_video(
state :: wgpu_state_t(),
id :: id_t(),
input_caps :: Membrane.RawVideo.t(),
position :: {x :: non_neg_integer(), y :: non_neg_integer()},
z :: float(),
scale :: float()
) :: :ok | {:error, error_t()}
def add_video(state, id, input_caps, {x, y}, z \\ 0.0, scale \\ 1.0) do
def put_video(state, id, input_caps, {x, y}, z \\ 0.0, scale \\ 1.0) do
{:ok, input_caps} = RustStructs.RawVideo.from_membrane_raw_video(input_caps)
properties = RustStructs.VideoProperties.from_tuple({x, y, z, scale})

case Native.add_video(state, id, input_caps, properties) do
case Native.put_video(state, id, input_caps, properties) do
:ok -> :ok
{:error, reason} -> raise "Error while adding a video, reason: #{inspect(reason)}"
end
end

@doc """
`x` and `y` are pixel coordinates specifying where the top-left corner of the video should be.
`z` must be a float between 0.0 and 1.0, and it determines which videos are drawn in front of others.
A video with a higher `z` coordinate will cover videos with lower `z` coordinates.
"""
@spec set_properties(
state :: wgpu_state_t(),
id :: id_t(),
position :: {x :: non_neg_integer(), y :: non_neg_integer()},
z :: float(),
scale :: float()
) :: :ok | {:error, error_t()}
def set_properties(state, id, {x, y}, z \\ 0.0, scale \\ 1.0) do
properties = RustStructs.VideoProperties.from_tuple({x, y, z, scale})

case Native.set_properties(state, id, properties) do
:ok -> :ok
{:error, reason} -> raise "Error while setting video properties, reason: #{inspect(reason)}"
end
end

@doc """
If the video doesn't exist this will return an error.
"""
Expand Down
4 changes: 2 additions & 2 deletions native/membrane_videocompositor/src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ impl State {
pts
}

pub fn add_video(&mut self, idx: usize, properties: VideoProperties) {
pub fn put_video(&mut self, idx: usize, properties: VideoProperties) {
self.input_videos.insert(
idx,
InputVideo::new(
Expand Down Expand Up @@ -434,7 +434,7 @@ mod tests {
let mut compositor = pollster::block_on(State::new(&caps)).unwrap();

for i in 0..n {
compositor.add_video(
compositor.put_video(
i,
VideoProperties {
top_left: Point {
Expand Down
17 changes: 3 additions & 14 deletions native/membrane_videocompositor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ fn force_render(
}

#[rustler::nif]
fn add_video(
fn put_video(
#[allow(unused)] env: rustler::Env<'_>,
state: rustler::ResourceArc<State>,
id: usize,
Expand All @@ -170,7 +170,7 @@ fn add_video(

let mut state: std::sync::MutexGuard<InnerState> = state.lock().unwrap();

state.compositor.add_video(
state.compositor.put_video(
id,
compositor::VideoProperties {
top_left: compositor::Point {
Expand All @@ -188,16 +188,6 @@ fn add_video(
Ok(atoms::ok())
}

#[rustler::nif]
fn set_properties(
#[allow(unused_variables)] env: rustler::Env<'_>,
_state: rustler::ResourceArc<State>,
_id: usize,
_properties: VideoProperties,
) -> Result<rustler::Atom, rustler::Error> {
Err(errors::CompositorError::NotImplemented.into())
}

#[rustler::nif]
fn remove_video(
#[allow(unused)] env: rustler::Env<'_>,
Expand All @@ -224,9 +214,8 @@ rustler::init!(
[
init,
force_render,
add_video,
put_video,
remove_video,
set_properties,
upload_frame,
send_end_of_stream
],
Expand Down
8 changes: 4 additions & 4 deletions test/wgpu/simple_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ defmodule VideoCompositor.Wgpu.Test do
})

assert :ok =
Native.add_video(state, 0, in_video, %VideoProperties{
Native.put_video(state, 0, in_video, %VideoProperties{
x: 0,
y: 0,
z: 0.0,
scale: 1.0
})

assert :ok =
Native.add_video(state, 1, in_video, %VideoProperties{
Native.put_video(state, 1, in_video, %VideoProperties{
x: 0,
y: 360,
z: 0.0,
Expand Down Expand Up @@ -85,15 +85,15 @@ defmodule VideoCompositor.Wgpu.Test do
assert {:ok, state} = Native.init(caps)

assert :ok =
Native.add_video(state, 0, caps, %VideoProperties{
Native.put_video(state, 0, caps, %VideoProperties{
x: 0,
y: 0,
z: 0.0,
scale: 1.0
})

assert :ok =
Native.add_video(state, 1, caps, %VideoProperties{
Native.put_video(state, 1, caps, %VideoProperties{
x: 0,
y: 0,
z: 0.5,
Expand Down