Skip to content

Commit

Permalink
Revert "Add :enforce_transcoding? option"
Browse files Browse the repository at this point in the history
This reverts commit 0930e72.
  • Loading branch information
FelonEkonom committed Feb 21, 2025
1 parent 0930e72 commit 1845179
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 98 deletions.
43 changes: 13 additions & 30 deletions lib/boombox.ex
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ defmodule Boombox do
| {:stream, out_stream_opts()}

@typep procs :: %{pipeline: pid(), supervisor: pid()}
@typep opts_map :: %{input: input(), output: output(), enforce_transcoding?: boolean()}
@typep opts_map :: %{input: input(), output: output()}

@doc """
Runs boombox with given input and output.
Expand All @@ -101,30 +101,13 @@ defmodule Boombox do
If the input is `{:stream, opts}`, a `Stream` or other `Enumerable` is expected
as the first argument.
If `:enforce_transcoding?` options is set to `true`, boombox will perform audio and/or video
transcoding, even if it is not necessary. By default this option is set to `false`.
```
Boombox.run(input: "path/to/file.mp4", output: {:webrtc, "ws://0.0.0.0:1234"}, enforce_transcoding?: true)
```
"""
@spec run(Enumerable.t() | nil,
input: input(),
output: output(),
enforce_transcoding?: boolean()
) :: :ok | Enumerable.t()
@endpoint_opts [:input, :output]
@spec run(Enumerable.t() | nil, input: input(), output: output()) :: :ok | Enumerable.t()
def run(stream \\ nil, opts) do
opts =
opts
|> Keyword.validate!(@endpoint_opts ++ [enforce_transcoding?: false])
|> Map.new(fn
{key, value} when key in @endpoint_opts -> {key, parse_endpoint_opt!(key, value)}
{key, value} -> {key, value}
end)

if key = Enum.find(@endpoint_opts, fn k -> not is_map_key(opts, k) end) do
opts_keys = [:input, :output]
opts = Keyword.validate!(opts, opts_keys) |> Map.new(fn {k, v} -> {k, parse_opt!(k, v)} end)

if key = Enum.find(opts_keys, fn k -> not is_map_key(opts, k) end) do
raise "#{key} is not provided"
end

Expand Down Expand Up @@ -172,9 +155,9 @@ defmodule Boombox do
end
end

@spec parse_endpoint_opt!(:input, input()) :: input()
@spec parse_endpoint_opt!(:output, output()) :: output()
defp parse_endpoint_opt!(direction, value) when is_binary(value) do
@spec parse_opt!(:input, input()) :: input()
@spec parse_opt!(:output, output()) :: output()
defp parse_opt!(direction, value) when is_binary(value) do
uri = URI.parse(value)
scheme = uri.scheme
extension = if uri.path, do: Path.extname(uri.path)
Expand All @@ -187,14 +170,14 @@ defmodule Boombox do
{nil, ".m3u8", :output} -> {:hls, value}
_other -> raise ArgumentError, "Unsupported URI: #{value} for direction: #{direction}"
end
|> then(&parse_endpoint_opt!(direction, &1))
|> then(&parse_opt!(direction, &1))
end

# credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
defp parse_endpoint_opt!(direction, value) when is_tuple(value) do
defp parse_opt!(direction, value) when is_tuple(value) do
case value do
{:mp4, location} when is_binary(location) and direction == :input ->
parse_endpoint_opt!(:input, {:mp4, location, []})
parse_opt!(:input, {:mp4, location, []})

{:mp4, location, opts} when is_binary(location) and direction == :input ->
if Keyword.keyword?(opts),
Expand All @@ -210,7 +193,7 @@ defmodule Boombox do
value

{:whip, uri} when is_binary(uri) ->
parse_endpoint_opt!(direction, {:whip, uri, []})
parse_opt!(direction, {:whip, uri, []})

{:whip, uri, opts} when is_binary(uri) and is_list(opts) ->
if Keyword.keyword?(opts) do
Expand Down
11 changes: 4 additions & 7 deletions lib/boombox/elixir_stream.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ defmodule Boombox.ElixirStream do
consumer :: pid,
options :: Boombox.out_stream_opts(),
Boombox.Pipeline.track_builders(),
Membrane.ChildrenSpec.t(),
boolean()
Membrane.ChildrenSpec.t()
) :: Ready.t()
def link_output(consumer, options, track_builders, spec_builder, enforce_transcoding?) do
def link_output(consumer, options, track_builders, spec_builder) do
options = parse_options(options, :output)

{track_builders, to_ignore} =
Expand All @@ -57,8 +56,7 @@ defmodule Boombox.ElixirStream do
{:audio, builder} ->
builder
|> child(:mp4_audio_transcoder, %Membrane.Transcoder{
output_stream_format: Membrane.RawAudio,
enforce_transcoding?: enforce_transcoding?
output_stream_format: Membrane.RawAudio
})
|> maybe_plug_resampler(options)
|> via_in(Pad.ref(:input, :audio))
Expand All @@ -67,8 +65,7 @@ defmodule Boombox.ElixirStream do
{:video, builder} ->
builder
|> child(:elixir_stream_video_transcoder, %Membrane.Transcoder{
output_stream_format: Membrane.RawVideo,
enforce_transcoding?: enforce_transcoding?
output_stream_format: Membrane.RawVideo
})
|> child(:elixir_stream_rgb_converter, %Membrane.FFmpeg.SWScale.Converter{
format: :RGB
Expand Down
11 changes: 4 additions & 7 deletions lib/boombox/hls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ defmodule Boombox.HLS do
@spec link_output(
Path.t(),
Boombox.Pipeline.track_builders(),
Membrane.ChildrenSpec.t(),
boolean()
Membrane.ChildrenSpec.t()
) :: Ready.t()
def link_output(location, track_builders, spec_builder, enforce_transcoding?) do
def link_output(location, track_builders, spec_builder) do
{directory, manifest_name} =
if Path.extname(location) == ".m3u8" do
{Path.dirname(location), Path.basename(location, ".m3u8")}
Expand Down Expand Up @@ -45,8 +44,7 @@ defmodule Boombox.HLS do
{:audio, builder} ->
builder
|> child(:hls_audio_transcoder, %Membrane.Transcoder{
output_stream_format: Membrane.AAC,
enforce_transcoding?: enforce_transcoding?
output_stream_format: Membrane.AAC
})
|> via_in(Pad.ref(:input, :audio),
options: [encoding: :AAC, segment_duration: Time.milliseconds(2000)]
Expand All @@ -56,8 +54,7 @@ defmodule Boombox.HLS do
{:video, builder} ->
builder
|> child(:hls_video_transcoder, %Membrane.Transcoder{
output_stream_format: %H264{alignment: :au, stream_structure: :avc3},
enforce_transcoding?: enforce_transcoding?
output_stream_format: %H264{alignment: :au, stream_structure: :avc3}
})
|> via_in(Pad.ref(:input, :video),
options: [encoding: :H264, segment_duration: Time.milliseconds(2000)]
Expand Down
11 changes: 4 additions & 7 deletions lib/boombox/mp4.ex
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ defmodule Boombox.MP4 do
@spec link_output(
String.t(),
Boombox.Pipeline.track_builders(),
Membrane.ChildrenSpec.t(),
boolean()
Membrane.ChildrenSpec.t()
) :: Ready.t()
def link_output(location, track_builders, spec_builder, enforce_transcoding?) do
def link_output(location, track_builders, spec_builder) do
spec =
[
spec_builder,
Expand All @@ -67,8 +66,7 @@ defmodule Boombox.MP4 do
{:audio, builder} ->
builder
|> child(:mp4_audio_transcoder, %Membrane.Transcoder{
output_stream_format: Membrane.AAC,
enforce_transcoding?: enforce_transcoding?
output_stream_format: Membrane.AAC
})
|> child(:mp4_out_aac_parser, %Membrane.AAC.Parser{
out_encapsulation: :none,
Expand All @@ -92,8 +90,7 @@ defmodule Boombox.MP4 do

_not_h26x ->
%H264{stream_structure: :avc3, alignment: :au}
end,
enforce_transcoding?: enforce_transcoding?
end
})
|> via_in(Pad.ref(:input, :video))
|> get_child(:mp4_muxer)
Expand Down
26 changes: 9 additions & 17 deletions lib/boombox/pipeline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ defmodule Boombox.Pipeline do
defmodule State do
@moduledoc false

@enforce_keys [:status, :input, :output, :parent, :enforce_transcoding?]
@enforce_keys [:status, :input, :output, :parent]

defstruct @enforce_keys ++
[
Expand Down Expand Up @@ -95,8 +95,7 @@ defmodule Boombox.Pipeline do
eos_info: term(),
rtsp_state: Boombox.RTSP.state() | nil,
parent: pid(),
output_webrtc_state: Boombox.WebRTC.output_webrtc_state() | nil,
enforce_transcoding?: boolean()
output_webrtc_state: Boombox.WebRTC.output_webrtc_state() | nil
}
end

Expand All @@ -106,7 +105,6 @@ defmodule Boombox.Pipeline do
input: opts.input,
output: opts.output,
parent: opts.parent,
enforce_transcoding?: opts.enforce_transcoding?,
status: :init
}

Expand Down Expand Up @@ -358,26 +356,20 @@ defmodule Boombox.Pipeline do
Boombox.WebRTC.link_output(track_builders, spec_builder, tracks, state)
end

defp link_output({:mp4, location}, track_builders, spec_builder, _ctx, state) do
Boombox.MP4.link_output(location, track_builders, spec_builder, state.enforce_transcoding?)
defp link_output({:mp4, location}, track_builders, spec_builder, _ctx, _state) do
Boombox.MP4.link_output(location, track_builders, spec_builder)
end

defp link_output({:hls, location}, track_builders, spec_builder, _ctx, state) do
Boombox.HLS.link_output(location, track_builders, spec_builder, state.enforce_transcoding?)
defp link_output({:hls, location}, track_builders, spec_builder, _ctx, _state) do
Boombox.HLS.link_output(location, track_builders, spec_builder)
end

defp link_output({:rtp, opts}, track_builders, spec_builder, _ctx, state) do
Boombox.RTP.link_output(opts, track_builders, spec_builder, state.enforce_transcoding?)
defp link_output({:rtp, opts}, track_builders, spec_builder, _ctx, _state) do
Boombox.RTP.link_output(opts, track_builders, spec_builder)
end

defp link_output({:stream, opts}, track_builders, spec_builder, _ctx, state) do
Boombox.ElixirStream.link_output(
state.parent,
opts,
track_builders,
spec_builder,
state.enforce_transcoding?
)
Boombox.ElixirStream.link_output(state.parent, opts, track_builders, spec_builder)
end

# Wait between sending the last packet
Expand Down
8 changes: 3 additions & 5 deletions lib/boombox/rtp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,9 @@ defmodule Boombox.RTP do
@spec link_output(
Boombox.out_rtp_opts(),
Boombox.Pipeline.track_builders(),
Membrane.ChildrenSpec.t(),
boolean()
Membrane.ChildrenSpec.t()
) :: Ready.t()
def link_output(opts, track_builders, spec_builder, enforce_transcoding?) do
def link_output(opts, track_builders, spec_builder) do
parsed_opts = validate_and_parse_options(:output, opts)

spec = [
Expand Down Expand Up @@ -165,8 +164,7 @@ defmodule Boombox.RTP do

builder
|> child({:rtp_transcoder, media_type}, %Membrane.Transcoder{
output_stream_format: output_stream_format,
enforce_transcoding?: enforce_transcoding?
output_stream_format: output_stream_format
})
|> child({:rtp_out_parser, media_type}, parser)
|> child({:rtp_payloader, media_type}, payloader)
Expand Down
17 changes: 4 additions & 13 deletions lib/boombox/webrtc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,8 @@ defmodule Boombox.WebRTC do
%{negotiated_video_codecs: [codec]} ->
{codec, [:h264, :vp8]}

%{negotiated_video_codecs: [_codec_1, _codec_2] = codecs}
when state.enforce_transcoding? ->
# we prefer H264 here because H264 Encoder cosumes less CPU than VP8 Encoder
{:h264, codecs}

%{negotiated_video_codecs: [_codec_1, _codec_2] = codecs} ->
# if we don't have to encode the video, we choose VP8 because sometimes there
# are some bugs in H264 support in Chrome
{:vp8, codecs}
%{negotiated_video_codecs: both} when is_list(both) ->
{:vp8, both}
end

spec =
Expand Down Expand Up @@ -155,8 +148,7 @@ defmodule Boombox.WebRTC do
{:audio, builder} ->
builder
|> child(:mp4_audio_transcoder, %Membrane.Transcoder{
output_stream_format: Membrane.Opus,
enforce_transcoding?: state.enforce_transcoding?
output_stream_format: Membrane.Opus
})
|> child(:webrtc_out_audio_realtimer, Membrane.Realtimer)
|> via_in(Pad.ref(:input, tracks.audio), options: [kind: :audio])
Expand Down Expand Up @@ -185,8 +177,7 @@ defmodule Boombox.WebRTC do

_format when vp8_negotiated? ->
VP8
end,
enforce_transcoding?: state.enforce_transcoding?
end
})
|> via_in(Pad.ref(:input, tracks.video), options: [kind: :video])
|> get_child(:webrtc_output)
Expand Down
5 changes: 1 addition & 4 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ defmodule Boombox.Mixfile do
defp deps do
[
{:membrane_core, "~> 1.1"},
# {:membrane_transcoder_plugin, "~> 0.1.2"},
{:membrane_transcoder_plugin,
github: "membraneframework/membrane_transcoder_plugin",
ref: "9a6fbbb2318b5ac4c2ecbd77c5845d3e0ca62531"},
{:membrane_transcoder_plugin, "~> 0.1.2"},
{:membrane_webrtc_plugin, "~> 0.24.0"},
{:membrane_mp4_plugin, "~> 0.35.2"},
{:membrane_realtimer_plugin, "~> 0.9.0"},
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"membrane_tee_plugin": {:hex, :membrane_tee_plugin, "0.12.0", "f94989b4080ef4b7937d74c1a14d3379577c7bd4c6d06e5a2bb41c351ad604d4", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "0d61c9ed5e68e5a75d54200e1c6df5739c0bcb52fee0974183ad72446a179887"},
"membrane_telemetry_metrics": {:hex, :membrane_telemetry_metrics, "0.1.1", "57917e72012f9ebe124eab54f29ca74c9d9eb3ae2207f55c95618ee51280eb4f", [:mix], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.1 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "69392966e6bd51937244758c2b3d835c5ff47d8953d25431a9d37059737afc11"},
"membrane_timestamp_queue": {:hex, :membrane_timestamp_queue, "0.2.2", "1c831b2273d018a6548654aa9f7fa7c4b683f71d96ffe164934ef55f9d11f693", [:mix], [{:heap, "~> 2.0", [hex: :heap, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "7c830e760baaced0988421671cd2c83c7cda8d1bd2b61fd05332711675d1204f"},
"membrane_transcoder_plugin": {:git, "https://github.com/membraneframework/membrane_transcoder_plugin.git", "9a6fbbb2318b5ac4c2ecbd77c5845d3e0ca62531", [ref: "9a6fbbb2318b5ac4c2ecbd77c5845d3e0ca62531"]},
"membrane_transcoder_plugin": {:hex, :membrane_transcoder_plugin, "0.1.2", "5d5546971289109423c1d02c4a45bfce7133293d76f5850824663a4613e5a728", [:mix], [{:membrane_aac_fdk_plugin, "~> 0.18.0", [hex: :membrane_aac_fdk_plugin, repo: "hexpm", optional: false]}, {:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_aac_plugin, "~> 0.19.0", [hex: :membrane_aac_plugin, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.1", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_ffmpeg_swresample_plugin, "~> 0.20.0", [hex: :membrane_ffmpeg_swresample_plugin, repo: "hexpm", optional: false]}, {:membrane_funnel_plugin, "~> 0.9.1", [hex: :membrane_funnel_plugin, repo: "hexpm", optional: false]}, {:membrane_h264_ffmpeg_plugin, "~> 0.32.0", [hex: :membrane_h264_ffmpeg_plugin, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_h265_ffmpeg_plugin, "~> 0.4.2", [hex: :membrane_h265_ffmpeg_plugin, repo: "hexpm", optional: false]}, {:membrane_h265_format, "~> 0.2.0", [hex: :membrane_h265_format, repo: "hexpm", optional: false]}, {:membrane_h26x_plugin, "~> 0.10.0", [hex: :membrane_h26x_plugin, repo: "hexpm", optional: false]}, {:membrane_opus_format, "~> 0.3.0", [hex: :membrane_opus_format, repo: "hexpm", optional: false]}, {:membrane_opus_plugin, "~> 0.20.3", [hex: :membrane_opus_plugin, repo: "hexpm", optional: false]}, {:membrane_timestamp_queue, "~> 0.2.2", [hex: :membrane_timestamp_queue, repo: "hexpm", optional: false]}, {:membrane_vp8_format, "~> 0.5.0", [hex: :membrane_vp8_format, repo: "hexpm", optional: false]}, {:membrane_vpx_plugin, "~> 0.3.0", [hex: :membrane_vpx_plugin, repo: "hexpm", optional: false]}], "hexpm", "50297b922fdd39520125120782bf679f26be8965b31565b470fb51b6ef908873"},
"membrane_udp_plugin": {:hex, :membrane_udp_plugin, "0.14.0", "d533ee5f6fcdd0551ad690045cdb6c1a76307a155d9255cc4a4606f85774bc37", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:mockery, "~> 2.3.0", [hex: :mockery, repo: "hexpm", optional: false]}], "hexpm", "902d1a7aa228ec377482d53a605b100e20e0b6e59196f94f94147bb62b23c47e"},
"membrane_vp8_format": {:hex, :membrane_vp8_format, "0.5.0", "a589c20bb9d97ddc9b717684d00cefc84e2500ce63a0c33c4b9618d9b2f9b2ea", [:mix], [], "hexpm", "d29e0dae4bebc6838e82e031c181fe626d168c687e4bc617c1d0772bdeed19d5"},
"membrane_vp9_format": {:hex, :membrane_vp9_format, "0.5.0", "c6a4f2cbfc39dba5d80ad8287162c52b5cf6488676bd64435c1ac957bd16e66f", [:mix], [], "hexpm", "68752d8cbe7270ec222fc84a7d1553499f0d8ff86ef9d9e89f8955d49e20278e"},
Expand Down
12 changes: 5 additions & 7 deletions test/browser_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,15 @@ defmodule Boombox.BrowserTest do
assert size > 400_000
end

for first <- [:ingress, :egress], transcoding? <- [true, false] do
test "browser -> boombox -> browser, but #{first} browser page connects first and :enforce_transcoding? is set to #{transcoding?}",
%{
browser: browser
} do
for first <- [:ingress, :egress] do
test "browser -> boombox -> browser, but #{first} browser page connects first", %{
browser: browser
} do
boombox_task =
Task.async(fn ->
Boombox.run(
input: {:webrtc, "ws://localhost:8829"},
output: {:webrtc, "ws://localhost:8830"},
enforce_transcoding?: unquote(transcoding?)
output: {:webrtc, "ws://localhost:8830"}
)
end)

Expand Down

0 comments on commit 1845179

Please sign in to comment.