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

Fix bouncing logo example, add appropriate test #64

Merged
merged 4 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 6 additions & 2 deletions examples.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ System.put_env("PATH", "/opt/homebrew/bin:#{System.get_env("PATH")}")

# MIX_INSTALL_CONFIG_BEGIN
boombox = {:boombox, github: "membraneframework/boombox"}

# This livebook uses boombox from the master branch. If any examples happen to not work, the latest stable version of this livebook
# can be found on https://hexdocs.pm/boombox/examples.html or in the latest github release.
# MIX_INSTALL_CONFIG_END
Expand Down Expand Up @@ -90,7 +91,10 @@ To send the stream, visit http://localhost:1234/whip.html.
Note: don't stop this cell to finish recording - click 'disconnect' or close the browser tab instead, so the recording is finalized properly.

```elixir
Boombox.run(input: {:whip, "http://localhost:8829", token: "whip_it!"}, output: "#{out_dir}/webrtc_to_mp4.mp4")
Boombox.run(
input: {:whip, "http://localhost:8829", token: "whip_it!"},
output: "#{out_dir}/webrtc_to_mp4.mp4"
)
```

```elixir
Expand Down Expand Up @@ -509,7 +513,7 @@ System.shell("ffplay #{out_dir}/rtmp_to_mp4.mp4")
## Stream MP4 via WebRTC, receive it and record to MP4 again

```elixir
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()

t =
Task.async(fn ->
Expand Down
4 changes: 2 additions & 2 deletions lib/boombox.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Boombox do

alias Membrane.RTP

@type webrtc_signaling :: Membrane.WebRTC.SignalingChannel.t() | String.t()
@type webrtc_signaling :: Membrane.WebRTC.Signaling.t() | String.t()
@type in_stream_opts :: [
{:audio, :binary | boolean()}
| {:video, :image | boolean()}
Expand Down Expand Up @@ -186,7 +186,7 @@ defmodule Boombox do
{:mp4, location} when is_binary(location) and direction == :output ->
{:mp4, location}

{:webrtc, %Membrane.WebRTC.SignalingChannel{}} ->
{:webrtc, %Membrane.WebRTC.Signaling{}} ->
value

{:webrtc, uri} when is_binary(uri) ->
Expand Down
10 changes: 5 additions & 5 deletions lib/boombox/webrtc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ defmodule Boombox.WebRTC do
if webrtc_input?(state) do
# let's spawn websocket server for webrtc source before the source starts
{:webrtc, input_signaling} = state.input
signaling_channel = resolve_signaling(input_signaling, :input, ctx.utility_supervisor)
state = %{state | input: {:webrtc, signaling_channel}}
signaling = resolve_signaling(input_signaling, :input, ctx.utility_supervisor)
state = %{state | input: {:webrtc, signaling}}

{%Wait{actions: [spec: spec]}, state}
else
Expand Down Expand Up @@ -188,7 +188,7 @@ defmodule Boombox.WebRTC do
end

defp resolve_signaling(
%WebRTC.SignalingChannel{} = signaling,
%WebRTC.Signaling{} = signaling,
_direction,
_utility_supervisor
) do
Expand All @@ -202,7 +202,7 @@ defmodule Boombox.WebRTC do
end

defp resolve_signaling({:whip, uri, opts}, :output, utility_supervisor) do
signaling = WebRTC.SignalingChannel.new()
signaling = WebRTC.Signaling.new()

Membrane.UtilitySupervisor.start_link_child(
utility_supervisor,
Expand All @@ -221,7 +221,7 @@ defmodule Boombox.WebRTC do
end

defp setup_whip_server(opts, utility_supervisor) do
signaling = WebRTC.SignalingChannel.new()
signaling = WebRTC.Signaling.new()
clients_cnt = :atomics.new(1, [])
{valid_token, opts} = Keyword.pop(opts, :token)

Expand Down
3 changes: 1 addition & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ defmodule Boombox.Mixfile do
[
{:membrane_core, "~> 1.1"},
{:membrane_transcoder_plugin, "~> 0.1.2"},
# {:membrane_webrtc_plugin, "~> 0.23.2"},
{:membrane_webrtc_plugin, github: "membraneframework/membrane_webrtc_plugin"},
{:membrane_webrtc_plugin, "~> 0.24.0"},
{:membrane_mp4_plugin, "~> 0.35.2"},
{:membrane_realtimer_plugin, "~> 0.9.0"},
{:membrane_http_adaptive_stream_plugin, "~> 0.18.5"},
Expand Down
22 changes: 11 additions & 11 deletions mix.lock

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions test/boombox_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ defmodule BoomboxTest do
@tag :file_webrtc
async_test "mp4 file -> webrtc -> mp4 file", %{tmp_dir: tmp} do
output = Path.join(tmp, "output.mp4")
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()
t = Task.async(fn -> Boombox.run(input: @bbb_mp4, output: {:webrtc, signaling}) end)
Boombox.run(input: {:webrtc, signaling}, output: output)
Task.await(t)
Expand All @@ -90,7 +90,7 @@ defmodule BoomboxTest do
@tag :http_webrtc
async_test "http mp4 -> webrtc -> mp4 file", %{tmp_dir: tmp} do
output = Path.join(tmp, "output.mp4")
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()
t = Task.async(fn -> Boombox.run(input: @bbb_mp4_url, output: {:webrtc, signaling}) end)
Boombox.run(input: {:webrtc, signaling}, output: output)
Task.await(t)
Expand All @@ -100,7 +100,7 @@ defmodule BoomboxTest do
@tag :webrtc_audio
async_test "mp4 -> webrtc -> mp4 audio", %{tmp_dir: tmp} do
output = Path.join(tmp, "output.mp4")
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()

t =
Task.async(fn -> Boombox.run(input: @bbb_mp4_a, output: {:webrtc, signaling}) end)
Expand All @@ -113,7 +113,7 @@ defmodule BoomboxTest do
@tag :webrtc_video
async_test "mp4 -> webrtc -> mp4 video", %{tmp_dir: tmp} do
output = Path.join(tmp, "output.mp4")
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()

t =
Task.async(fn -> Boombox.run(input: @bbb_mp4_v, output: {:webrtc, signaling}) end)
Expand All @@ -126,8 +126,8 @@ defmodule BoomboxTest do
@tag :webrtc2
async_test "mp4 -> webrtc -> webrtc -> mp4", %{tmp_dir: tmp} do
output = Path.join(tmp, "output.mp4")
signaling1 = Membrane.WebRTC.SignalingChannel.new()
signaling2 = Membrane.WebRTC.SignalingChannel.new()
signaling1 = Membrane.WebRTC.Signaling.new()
signaling2 = Membrane.WebRTC.Signaling.new()

t1 =
Task.async(fn -> Boombox.run(input: @bbb_mp4, output: {:webrtc, signaling1}) end)
Expand Down Expand Up @@ -198,7 +198,7 @@ defmodule BoomboxTest do
async_test "rtmp -> webrtc -> mp4", %{tmp_dir: tmp} do
output = Path.join(tmp, "output.mp4")
url = "rtmp://localhost:5002/app/stream_key"
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()

t1 =
Task.async(fn -> Boombox.run(input: url, output: {:webrtc, signaling}) end)
Expand Down Expand Up @@ -279,7 +279,7 @@ defmodule BoomboxTest do
async_test "rtsp -> webrtc -> mp4", %{tmp_dir: tmp} do
rtsp_port = 8556
output = Path.join(tmp, "output.mp4")
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()

Membrane.SimpleRTSPServer.start_link(@bbb_mp4, port: rtsp_port)

Expand Down Expand Up @@ -314,7 +314,7 @@ defmodule BoomboxTest do

@tag :bouncing_bubble_webrtc_mp4
async_test "bouncing bubble -> webrtc -> mp4", %{tmp_dir: tmp} do
signaling = Membrane.WebRTC.SignalingChannel.new()
signaling = Membrane.WebRTC.Signaling.new()

Task.async(fn ->
overlay =
Expand Down
43 changes: 43 additions & 0 deletions test/browser_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,49 @@ defmodule Boombox.BrowserTest do
end
end

test "boombox -> browser (bouncing logo)", %{browser: browser} do
overlay =
__DIR__
|> Path.join("fixtures/logo.png")
|> Image.open!()

bg = Image.new!(640, 480, color: :light_gray)
max_x = Image.width(bg) - Image.width(overlay)
max_y = Image.height(bg) - Image.height(overlay)

stream =
Stream.iterate({_x = 300, _y = 0, _dx = 1, _dy = 2, _pts = 0}, fn {x, y, dx, dy, pts} ->
dx = if (x + dx) in 0..max_x, do: dx, else: -dx
dy = if (y + dy) in 0..max_y, do: dy, else: -dy
pts = pts + div(Membrane.Time.seconds(1), _fps = 60)
{x + dx, y + dy, dx, dy, pts}
end)
|> Stream.map(fn {x, y, _dx, _dy, pts} ->
img = Image.compose!(bg, overlay, x: x, y: y)
%Boombox.Packet{kind: :video, payload: img, pts: pts}
end)

boombox_task =
Task.async(fn ->
stream
|> Boombox.run(
input: {:stream, video: :image, audio: false},
output: {:webrtc, "ws://localhost:8830"}
)
end)

page = start_page(browser, "webrtc_to_browser")

seconds = 10
Process.sleep(seconds * 1000)

assert_page_connected(page)
assert_frames_decoded(page, seconds)

close_page(page)
Task.shutdown(boombox_task)
end

defp start_page(browser, page) do
url = "http://localhost:#{@port}/#{page}.html"
do_start_page(browser, url)
Expand Down
Binary file added test/fixtures/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.