From b0901b39d5a85fe09a07e624db02b6ffdd07e619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 17 Jul 2024 17:15:42 +0200 Subject: [PATCH 1/9] new rtmp api basic functionality works --- lib/boombox/pipeline.ex | 8 +++++ lib/boombox/rtmp.ex | 67 ++++++++++++++++++++++++----------------- mix.exs | 3 +- mix.lock | 31 +++++++++---------- test/boombox_test.exs | 2 +- 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/lib/boombox/pipeline.ex b/lib/boombox/pipeline.ex index 9c79a1f..098bae4 100644 --- a/lib/boombox/pipeline.ex +++ b/lib/boombox/pipeline.ex @@ -165,6 +165,14 @@ defmodule Boombox.Pipeline do proceed_result(result, ctx, %{state | rtmp_input_state: rtmp_input_state}) end + @impl true + def handle_info({:rtmp_client_ref, client_ref, app, stream_key}, ctx, state) do + {result, rtmp_input_state} = + Boombox.RTMP.handle_connection(client_ref, state) + + proceed_result(result, ctx, %{state | rtmp_input_state: rtmp_input_state}) + end + @impl true def handle_element_end_of_stream(:mp4_file_sink, :input, _ctx, state) do {[terminate: :normal], state} diff --git a/lib/boombox/rtmp.ex b/lib/boombox/rtmp.ex index 71915d0..d809d22 100644 --- a/lib/boombox/rtmp.ex +++ b/lib/boombox/rtmp.ex @@ -6,40 +6,35 @@ defmodule Boombox.RTMP do @type state :: %{server_pid: pid()} | nil - @spec create_input(URI.t(), pid()) :: Wait.t() + @spec create_input(URI.t(), pid()) :: {Wait.t(), state()} def create_input(uri, utility_supervisor) do + uri = URI.new!(uri) - {:ok, ip} = :inet.getaddr(~c"#{uri.host}", :inet) + [app | [stream_key]] = String.split(uri.path, "/", [trim: true]) boombox = self() - server_options = %Membrane.RTMP.Source.TcpServer{ - port: uri.port, - listen_options: [:binary, packet: :raw, active: false, ip: ip], - socket_handler: fn socket -> - send(boombox, {:rtmp_tcp_server, self(), socket}) - - receive do - {:rtmp_source_pid, pid} -> {:ok, pid} - :rtmp_already_connected -> {:error, :rtmp_already_connected} - end - end - } + new_client_callback = fn client_ref, app, stream_key -> + send(boombox, {:rtmp_client_ref, client_ref, app, stream_key}) + end - {:ok, _pid} = - Membrane.UtilitySupervisor.start_link_child( - utility_supervisor, - {Membrane.RTMP.Source.TcpServer, server_options} + # Run the standalone server + {:ok, server} = + Membrane.RTMP.Server.start_link( + handler: %Membrane.RTMP.Source.ClientHandler{controlling_process: self()}, + port: uri.port, + use_ssl?: false, + new_client_callback: new_client_callback, + client_timeout: 1_000 ) %Wait{} end - @spec handle_connection(pid(), :gen_tcp.socket() | :ssl.sslsocket(), state()) :: - {Ready.t(), state()} - def handle_connection(server_pid, socket, nil = _state) do + # @spec handle_connection(pid(), :gen_tcp.socket() | :ssl.sslsocket(), state()) :: {Ready.t(), state()} + def handle_connection(client_ref, state) do spec = [ - child(:rtmp_source, %Membrane.RTMP.SourceBin{socket: socket}) + child(:rtmp_source, %Membrane.RTMP.SourceBin{client_ref: client_ref}) |> via_out(:audio) |> child(Membrane.AAC.Parser) |> child(:aac_decoder, Membrane.AAC.FDK.Decoder) @@ -50,13 +45,31 @@ defmodule Boombox.RTMP do video: get_child(:rtmp_source) |> via_out(:video) } - {%Ready{spec_builder: spec, track_builders: track_builders}, %{server_pid: server_pid}} + {%Ready{spec_builder: spec, track_builders: track_builders}, state} end - def handle_connection(_server_pid, _socket, state) do - send(state.server_pid, :rtmp_already_connected) - {%Wait{}, state} - end + # @spec handle_connection(pid(), :gen_tcp.socket() | :ssl.sslsocket(), state()) :: + # {Ready.t(), state()} + # def handle_connection(client_ref, state) do + # spec = [ + # child(:rtmp_source, %Membrane.RTMP.SourceBin{client_ref: client_ref}) + # |> via_out(:audio) + # |> child(Membrane.AAC.Parser) + # |> child(:aac_decoder, Membrane.AAC.FDK.Decoder) + # ] + + # track_builders = %{ + # audio: get_child(:aac_decoder), + # video: get_child(:rtmp_source) |> via_out(:video) + # } + + # {%Ready{spec_builder: spec, track_builders: track_builders}, state} + # end + + # def handle_connection(_server_pid, _socket, state) do + # send(state.server_pid, :rtmp_already_connected) + # {%Wait{}, state} + # end @spec handle_socket_control(pid(), state()) :: Wait.t() def handle_socket_control(source_pid, state) do diff --git a/mix.exs b/mix.exs index c9a883e..9f88608 100644 --- a/mix.exs +++ b/mix.exs @@ -46,7 +46,8 @@ defmodule Boombox.Mixfile do {:membrane_mp4_plugin, github: "membraneframework/membrane_mp4_plugin", branch: "isom-avc3"}, {:membrane_realtimer_plugin, ">= 0.0.0"}, - {:membrane_rtmp_plugin, ">= 0.0.0"}, + # {:membrane_rtmp_plugin, ">= 0.0.0"}, + {:membrane_rtmp_plugin, path: "../membrane_rtmp_plugin"}, {:membrane_ffmpeg_swresample_plugin, ">= 0.0.0"}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:dialyxir, ">= 0.0.0", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 95ae329..1238e08 100644 --- a/mix.lock +++ b/mix.lock @@ -3,19 +3,19 @@ "bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"}, "bunch": {:hex, :bunch, "1.6.1", "5393d827a64d5f846092703441ea50e65bc09f37fd8e320878f13e63d410aec7", [:mix], [], "hexpm", "286cc3add551628b30605efbe2fca4e38cc1bea89bcd0a1a7226920b3364fe4a"}, "bunch_native": {:hex, :bunch_native, "0.5.0", "8ac1536789a597599c10b652e0b526d8833348c19e4739a0759a2bedfd924e63", [:mix], [{:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "24190c760e32b23b36edeb2dc4852515c7c5b3b8675b1a864e0715bdd1c8f80d"}, - "bundlex": {:hex, :bundlex, "1.5.1", "a85890a9d0a70366afa538c8589a4ba75e1319d32a771e1f5f3b7566beea9c26", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, "~> 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "aae447d63230fe1f3b788c429ac02bc696f30163d0f23f52fcfe6ed38372c7ea"}, + "bundlex": {:hex, :bundlex, "1.5.3", "35d01e5bc0679510dd9a327936ffb518f63f47175c26a35e708cc29eaec0890b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "debd0eac151b404f6216fc60222761dff049bf26f7d24d066c365317650cd118"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "castore": {:hex, :castore, "1.0.7", "b651241514e5f6956028147fe6637f7ac13802537e895a724f90bf3e36ddd1dd", [:mix], [], "hexpm", "da7785a4b0d2a021cd1292a60875a784b6caef71e76bf4917bdee1f390455cf5"}, + "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, "crc": {:hex, :crc, "0.10.5", "ee12a7c056ac498ef2ea985ecdc9fa53c1bfb4e53a484d9f17ff94803707dfd8", [:mix, :rebar3], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3e673b6495a9525c5c641585af1accba59a1eb33de697bedf341e247012c2c7f"}, "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, - "ex_doc": {:hex, :ex_doc, "0.34.1", "9751a0419bc15bc7580c73fde506b17b07f6402a1e5243be9e0f05a68c723368", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "d441f1a86a235f59088978eff870de2e815e290e44a8bd976fe5d64470a4c9d2"}, - "ex_dtls": {:hex, :ex_dtls, "0.15.1", "34b3600ff13eebf6c96be033005cc110ea5beef98394631365ec26b493df80c5", [:mix], [{:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "9cfebdfe9111c0f68c77667cb9366e4a6f17e8a240975ffd100148de57478a29"}, + "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, + "ex_dtls": {:hex, :ex_dtls, "0.15.2", "6c8c0f8eb67525216551bd3e0322ab33c9d851d56ef3e065efab4fd277a8fbb9", [:mix], [{:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "6b852bc926bbdc9c1b9c4ecc6cfc73a89d4e106042802cefea2c1503072a9f2a"}, "ex_ice": {:hex, :ex_ice, "0.7.1", "3ad14f7281ece304dfee227e332b8a67d93d5857602a8a4300a826c250af136e", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.1.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "78e6bc4abb5294dcf0a474d0a91e78a829916291d846a0e255867dc5db8733e7"}, "ex_libsrtp": {:hex, :ex_libsrtp, "0.7.2", "211bd89c08026943ce71f3e2c0231795b99cee748808ed3ae7b97cd8d2450b6b", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2e20645d0d739a4ecdcf8d4810a0c198120c8a2f617f2b75b2e2e704d59f492a"}, "ex_rtcp": {:hex, :ex_rtcp, "0.3.0", "c61d6aba0fefc0af92a4fa214be13cc34580b55a0a65c1d4ac74c88e4baae015", [:mix], [], "hexpm", "48a5667779dd97910e1e5dc7d3938881c0ee85cf5023799be4ede9526f960bd2"}, @@ -28,11 +28,11 @@ "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, "heap": {:hex, :heap, "2.0.2", "d98cb178286cfeb5edbcf17785e2d20af73ca57b5a2cf4af584118afbcf917eb", [:mix], [], "hexpm", "ba9ea2fe99eb4bcbd9a8a28eaf71cbcac449ca1d8e71731596aace9028c9d429"}, "hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"}, - "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, + "jason": {:hex, :jason, "1.4.3", "d3f984eeb96fe53b85d20e0b049f03e57d075b5acda3ac8d465c969a2536c17b", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "9a90e868927f7c777689baa16d86f4d0e086d968db5c05d917ccff6d443e58a3"}, "logger_backends": {:hex, :logger_backends, "1.0.0", "09c4fad6202e08cb0fbd37f328282f16539aca380f512523ce9472b28edc6bdf", [:mix], [], "hexpm", "1faceb3e7ec3ef66a8f5746c5afd020e63996df6fd4eb8cdb789e5665ae6c9ce"}, "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, - "makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"}, + "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, "membrane_aac_fdk_plugin": {:hex, :membrane_aac_fdk_plugin, "0.18.8", "88d47923805cbd9a977fc7e5d3eb8d3028a2e358ad9ad7b124684adc78c2e8ee", [:mix], [{:bunch, "~> 1.4", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_audio_format, "~> 0.12.0", [hex: :membrane_raw_audio_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "bb9e706d0949954affd4e295f5d3d4660096997756b5422119800d961c46cc63"}, "membrane_aac_format": {:hex, :membrane_aac_format, "0.8.0", "515631eabd6e584e0e9af2cea80471fee6246484dbbefc4726c1d93ece8e0838", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}], "hexpm", "a30176a94491033ed32be45e51d509fc70a5ee6e751f12fd6c0d60bd637013f6"}, "membrane_aac_plugin": {:hex, :membrane_aac_plugin, "0.18.1", "30433bffd4d5d773f79448dd9afd55d77338721688f09a89b20d742a68cc2c3d", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "8fd048c47d5d2949eb557e19f43f62d534d3af5096187f1a1a3a1694d14b772c"}, @@ -40,10 +40,10 @@ "membrane_common_c": {:hex, :membrane_common_c, "0.16.0", "caf3f29d2f5a1d32d8c2c122866110775866db2726e4272be58e66dfdf4bce40", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "a3c7e91de1ce1f8b23b9823188a5d13654d317235ea0ca781c05353ed3be9b1c"}, "membrane_core": {:hex, :membrane_core, "1.1.0", "c3bbaa5af7c26a7c3748e573efe343c2104801e3463b9e491a607e82860334a4", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0 or ~> 4.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3209d7f7e86d736cb7caffbba16b075c571cebb9439ab939ed6119c50fb59a5"}, "membrane_ffmpeg_swresample_plugin": {:hex, :membrane_ffmpeg_swresample_plugin, "0.20.2", "2e669f0b25418d10b51a73bc52d2e12e4a3a26b416c5c1199d852c3f781a18b3", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.2", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_audio_format, "~> 0.12.0", [hex: :membrane_raw_audio_format, repo: "hexpm", optional: false]}, {:mockery, "~> 2.1", [hex: :mockery, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "6c8d3bcd61d568dd94cabb9b45f29e8926e0076e4432d8f419378e004e02147c"}, - "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.17.0", "e855a848e84eaed537b41fd4436712038fc5518059eadc8609c83cd2d819653a", [:mix], [{:logger_backends, "~> 1.0", [hex: :logger_backends, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "9c3653ca9f13bb409b36257d6094798d4625c739ab7a4035c12308622eb16e0b"}, + "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.17.2", "650e134c2345d946f930082fac8bac9f5aba785a7817d38a9a9da41ffc56fa92", [:mix], [{:logger_backends, "~> 1.0", [hex: :logger_backends, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "df50c6040004cd7b901cf057bd7e99c875bbbd6ae574efc93b2c753c96f43b9d"}, "membrane_flv_plugin": {:hex, :membrane_flv_plugin, "0.12.0", "d715ad405af86dcaf4b2f479e34088e1f6738c7280366828e1066b39d2aa493a", [:mix], [{:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}], "hexpm", "a317872d6d394e550c7bfd8979f12a3a1cc1e89b547d75360321025b403d3279"}, "membrane_funnel_plugin": {:hex, :membrane_funnel_plugin, "0.9.0", "9cfe09e44d65751f7d9d8d3c42e14797f7be69e793ac112ea63cd224af70a7bf", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "988790aca59d453a6115109f050699f7f45a2eb6a7f8dc5c96392760cddead54"}, - "membrane_h264_ffmpeg_plugin": {:hex, :membrane_h264_ffmpeg_plugin, "0.31.6", "95574b1e2fea79f17c57db4295364ed82e2d57ab4ce229734421fde37e9bc632", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "30a45d79317c27c1402ab871e3e42b0244e6ecd72cbf1145aea337726cff7ac2"}, + "membrane_h264_ffmpeg_plugin": {:hex, :membrane_h264_ffmpeg_plugin, "0.32.0", "6032274dc01a41fe74806480e13ebded71f4833238554bca7ef2bfb8a48d5c97", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "09f6bc3a631aadb4fa9c8c6abaf97f375b94b94a2f24332d25ed4610d4ea5635"}, "membrane_h264_format": {:hex, :membrane_h264_format, "0.6.1", "44836cd9de0abe989b146df1e114507787efc0cf0da2368f17a10c47b4e0738c", [:mix], [], "hexpm", "4b79be56465a876d2eac2c3af99e115374bbdc03eb1dea4f696ee9a8033cd4b0"}, "membrane_h265_format": {:hex, :membrane_h265_format, "0.2.0", "1903c072cf7b0980c4d0c117ab61a2cd33e88782b696290de29570a7fab34819", [:mix], [], "hexpm", "6df418bdf242c0d9f7dbf2e5aea4c2d182e34ac9ad5a8b8cef2610c290002e83"}, "membrane_h26x_plugin": {:hex, :membrane_h26x_plugin, "0.10.2", "caf2790d8c107df35f8d456b45f4e09fb9c56ce6c7669a3a03f7d59972e6ed82", [:mix], [{:bunch, "~> 1.4", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.0", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_h265_format, "~> 0.2.0", [hex: :membrane_h265_format, repo: "hexpm", optional: false]}], "hexpm", "becf1ac4a589adecd850137ccd61a33058f686083a514a7e39fcd721bcf9fb2e"}, @@ -65,24 +65,23 @@ "membrane_telemetry_metrics": {:hex, :membrane_telemetry_metrics, "0.1.0", "cb93d28356b436b0597736c3e4153738d82d2a14ff547f831df7e9051e54fc06", [:mix], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.1", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "aba28dc8311f70ced95d984509be930fac55857d2d18bffcf768815e627be3f0"}, "membrane_vp8_format": {:hex, :membrane_vp8_format, "0.4.0", "6c29ec67479edfbab27b11266dc92f18f3baf4421262c5c31af348c33e5b92c7", [:mix], [], "hexpm", "8bb005ede61db8fcb3535a883f32168b251c2dfd1109197c8c3b39ce28ed08e2"}, "membrane_webrtc_plugin": {:hex, :membrane_webrtc_plugin, "0.20.0", "4d44de5382a35c13a1816f604c314115c0ec0b2def6dfe58d2c93521050e2fa0", [:mix], [{:bandit, "~> 1.2", [hex: :bandit, repo: "hexpm", optional: false]}, {:ex_webrtc, "~> 0.2.0", [hex: :ex_webrtc, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_rtp_h264_plugin, "~> 0.19.0", [hex: :membrane_rtp_h264_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_opus_plugin, "~> 0.9.0", [hex: :membrane_rtp_opus_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_plugin, "~> 0.27.1", [hex: :membrane_rtp_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_vp8_plugin, "~> 0.9.0", [hex: :membrane_rtp_vp8_plugin, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.0", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "9536a2ad0290b60184b6b21c013dc50a2f702280ae1e64f1298723f90aa67377"}, - "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, - "mint": {:hex, :mint, "1.6.1", "065e8a5bc9bbd46a41099dfea3e0656436c5cbcb6e741c80bd2bad5cd872446f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4fc518dcc191d02f433393a72a7ba3f6f94b101d094cb6bf532ea54c89423780"}, - "mockery": {:hex, :mockery, "2.3.1", "a02fd60b10ac9ed37a7a2ecf6786c1f1dd5c75d2b079a60594b089fba32dc087", [:mix], [], "hexpm", "1d0971d88ebf084e962da3f2cfee16f0ea8e04ff73a7710428500d4500b947fa"}, + "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, + "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, + "mockery": {:hex, :mockery, "2.3.3", "3dba87bd0422a513e6af6e0d811383f38f82ac6be5d3d285a5fcca9c299bd0ac", [:mix], [], "hexpm", "17282be00613286254298117cd25e607a39f15ac03b41c631f60e52f5b5ec974"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, - "nimble_ownership": {:hex, :nimble_ownership, "0.3.1", "99d5244672fafdfac89bfad3d3ab8f0d367603ce1dc4855f86a1c75008bce56f", [:mix], [], "hexpm", "4bf510adedff0449a1d6e200e43e57a814794c8b5b6439071274d248d272a549"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "numbers": {:hex, :numbers, "5.2.4", "f123d5bb7f6acc366f8f445e10a32bd403c8469bdbce8ce049e1f0972b607080", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "eeccf5c61d5f4922198395bf87a465b6f980b8b862dd22d28198c5e6fab38582"}, "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, - "ratio": {:hex, :ratio, "3.0.2", "60a5976872a4dc3d873ecc57eed1738589e99d1094834b9c935b118231297cfb", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "3a13ed5a30ad0bfd7e4a86bf86d93d2b5a06f5904417d38d3f3ea6406cdfc7bb"}, - "req": {:hex, :req, "0.4.14", "103de133a076a31044e5458e0f850d5681eef23dfabf3ea34af63212e3b902e2", [:mix], [{:aws_signature, "~> 0.3.2", [hex: :aws_signature, repo: "hexpm", optional: true]}, {:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:nimble_ownership, "~> 0.2.0 or ~> 0.3.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "2ddd3d33f9ab714ced8d3c15fd03db40c14dbf129003c4a3eb80fac2cc0b1b08"}, + "ratio": {:hex, :ratio, "4.0.1", "3044166f2fc6890aa53d3aef0c336f84b2bebb889dc57d5f95cc540daa1912f8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "c60cbb3ccdff9ffa56e7d6d1654b5c70d9f90f4d753ab3a43a6bf40855b881ce"}, + "req": {:hex, :req, "0.5.2", "70b4976e5fbefe84e5a57fd3eea49d4e9aa0ac015301275490eafeaec380f97f", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0c63539ab4c2d6ced6114d2684276cef18ac185ee00674ee9af4b1febba1f986"}, "shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"}, "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, - "unifex": {:hex, :unifex, "1.1.2", "ed3366515b6612a5a08d24a38658dea18a6c6001e79cf41e3a2edd07004d3c6d", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "c25b9d4d1a1c76716ecdf68d0873553fdab4105f418ef76f646a5cb47e0396ab"}, + "unifex": {:hex, :unifex, "1.2.0", "90d1ec5e6d788350e07e474f7bd8b0ee866d6606beb9ca4e20dbb26328712a84", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "7a8395aabc3ba6cff04bbe5b995de7f899a38eb57f189e49927d6b8b6ccb6883"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"}, "zarex": {:hex, :zarex, "1.0.5", "58239e3ee5d75f343262bb4df5cf466555a1c689f920e5d3651a9333972f7c7e", [:mix], [], "hexpm", "9fb72ef0567c2b2742f5119a1ba8a24a2fabb21b8d09820aefbf3e592fa9a46a"}, diff --git a/test/boombox_test.exs b/test/boombox_test.exs index 8354350..02a6f75 100644 --- a/test/boombox_test.exs +++ b/test/boombox_test.exs @@ -90,7 +90,7 @@ defmodule BoomboxTest do @tag :rtmp async_test "rtmp -> mp4", %{tmp_dir: tmp} do - url = "rtmp://localhost:5000" + url = "rtmp://localhost:5000/app/stream_key" t = Task.async(fn -> Boombox.run(input: url, output: "#{tmp}/output.mp4") end) # Wait for boombox to be ready From da1508290950c0043752dbb0b0bbc0346a5b4eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 17 Jul 2024 18:08:44 +0200 Subject: [PATCH 2/9] little refactor, format --- lib/boombox/pipeline.ex | 20 +++++------------- lib/boombox/rtmp.ex | 45 ++++++++++++----------------------------- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/lib/boombox/pipeline.ex b/lib/boombox/pipeline.ex index 098bae4..d7d5404 100644 --- a/lib/boombox/pipeline.ex +++ b/lib/boombox/pipeline.ex @@ -158,19 +158,9 @@ defmodule Boombox.Pipeline do end @impl true - def handle_info({:rtmp_tcp_server, server_pid, socket}, ctx, state) do - {result, rtmp_input_state} = - Boombox.RTMP.handle_connection(server_pid, socket, state.rtmp_input_state) - - proceed_result(result, ctx, %{state | rtmp_input_state: rtmp_input_state}) - end - - @impl true - def handle_info({:rtmp_client_ref, client_ref, app, stream_key}, ctx, state) do - {result, rtmp_input_state} = - Boombox.RTMP.handle_connection(client_ref, state) - - proceed_result(result, ctx, %{state | rtmp_input_state: rtmp_input_state}) + def handle_info({:rtmp_client_ref, client_ref}, ctx, state) do + Boombox.RTMP.handle_connection(client_ref) + |> proceed_result(ctx, state) end @impl true @@ -273,8 +263,8 @@ defmodule Boombox.Pipeline do Boombox.MP4.create_input(location) end - defp create_input([:rtmp, uri], ctx) do - Boombox.RTMP.create_input(uri, ctx.utility_supervisor) + defp create_input([:rtmp, uri], _ctx) do + Boombox.RTMP.create_input(uri) end @spec create_output(Boombox.output(), Membrane.Pipeline.CallbackContext.t()) :: diff --git a/lib/boombox/rtmp.ex b/lib/boombox/rtmp.ex index d809d22..ab288af 100644 --- a/lib/boombox/rtmp.ex +++ b/lib/boombox/rtmp.ex @@ -2,24 +2,28 @@ defmodule Boombox.RTMP do @moduledoc false import Membrane.ChildrenSpec + require Membrane.Logger alias Boombox.Pipeline.{Ready, Wait} @type state :: %{server_pid: pid()} | nil - @spec create_input(URI.t(), pid()) :: {Wait.t(), state()} - def create_input(uri, utility_supervisor) do - + @spec create_input(URI.t()) :: Wait.t() + def create_input(uri) do uri = URI.new!(uri) - [app | [stream_key]] = String.split(uri.path, "/", [trim: true]) + [target_app | [target_stream_key]] = String.split(uri.path, "/", trim: true) boombox = self() new_client_callback = fn client_ref, app, stream_key -> - send(boombox, {:rtmp_client_ref, client_ref, app, stream_key}) + if app == target_app and stream_key == target_stream_key do + send(boombox, {:rtmp_client_ref, client_ref}) + else + Membrane.Logger.warning("Unexpected client connected on /#{app}/#{stream_key}") + end end # Run the standalone server - {:ok, server} = + {:ok, _server} = Membrane.RTMP.Server.start_link( handler: %Membrane.RTMP.Source.ClientHandler{controlling_process: self()}, port: uri.port, @@ -31,8 +35,8 @@ defmodule Boombox.RTMP do %Wait{} end - # @spec handle_connection(pid(), :gen_tcp.socket() | :ssl.sslsocket(), state()) :: {Ready.t(), state()} - def handle_connection(client_ref, state) do + @spec handle_connection(pid()) :: Ready.t() + def handle_connection(client_ref) do spec = [ child(:rtmp_source, %Membrane.RTMP.SourceBin{client_ref: client_ref}) |> via_out(:audio) @@ -45,32 +49,9 @@ defmodule Boombox.RTMP do video: get_child(:rtmp_source) |> via_out(:video) } - {%Ready{spec_builder: spec, track_builders: track_builders}, state} + %Ready{spec_builder: spec, track_builders: track_builders} end - # @spec handle_connection(pid(), :gen_tcp.socket() | :ssl.sslsocket(), state()) :: - # {Ready.t(), state()} - # def handle_connection(client_ref, state) do - # spec = [ - # child(:rtmp_source, %Membrane.RTMP.SourceBin{client_ref: client_ref}) - # |> via_out(:audio) - # |> child(Membrane.AAC.Parser) - # |> child(:aac_decoder, Membrane.AAC.FDK.Decoder) - # ] - - # track_builders = %{ - # audio: get_child(:aac_decoder), - # video: get_child(:rtmp_source) |> via_out(:video) - # } - - # {%Ready{spec_builder: spec, track_builders: track_builders}, state} - # end - - # def handle_connection(_server_pid, _socket, state) do - # send(state.server_pid, :rtmp_already_connected) - # {%Wait{}, state} - # end - @spec handle_socket_control(pid(), state()) :: Wait.t() def handle_socket_control(source_pid, state) do send(state.server_pid, {:rtmp_source_pid, source_pid}) From e97f19025d357674355f87aedf77ce77ae8a1bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Thu, 18 Jul 2024 15:16:06 +0200 Subject: [PATCH 3/9] code cleanup --- lib/boombox/pipeline.ex | 11 ----------- lib/boombox/rtmp.ex | 15 ++++++++++----- mix.exs | 3 ++- mix.lock | 2 +- test/boombox_test.exs | 3 ++- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/lib/boombox/pipeline.ex b/lib/boombox/pipeline.ex index d7d5404..6952099 100644 --- a/lib/boombox/pipeline.ex +++ b/lib/boombox/pipeline.ex @@ -115,17 +115,6 @@ defmodule Boombox.Pipeline do |> proceed_result(ctx, state) end - @impl true - def handle_child_notification( - {:socket_control_needed, _socket, source_pid}, - :rtmp_source, - ctx, - state - ) do - Boombox.RTMP.handle_socket_control(source_pid, state.rtmp_input_state) - |> proceed_result(ctx, state) - end - @impl true def handle_child_notification({:new_tracks, tracks}, :webrtc_output, ctx, state) do %{status: :awaiting_output_link} = state diff --git a/lib/boombox/rtmp.ex b/lib/boombox/rtmp.ex index ab288af..8782f96 100644 --- a/lib/boombox/rtmp.ex +++ b/lib/boombox/rtmp.ex @@ -10,7 +10,8 @@ defmodule Boombox.RTMP do @spec create_input(URI.t()) :: Wait.t() def create_input(uri) do uri = URI.new!(uri) - [target_app | [target_stream_key]] = String.split(uri.path, "/", trim: true) + + {target_app, target_stream_key} = get_app_stream_key_from_path(uri.path) boombox = self() @@ -52,9 +53,13 @@ defmodule Boombox.RTMP do %Ready{spec_builder: spec, track_builders: track_builders} end - @spec handle_socket_control(pid(), state()) :: Wait.t() - def handle_socket_control(source_pid, state) do - send(state.server_pid, {:rtmp_source_pid, source_pid}) - %Wait{} + defp get_app_stream_key_from_path(path) do + case String.split(path, "/", trim: true) do + [app | [stream_key]] -> + {app, stream_key} + + _error -> + raise "Invalid RTMP URI path #{inspect(path)}, expected /{app}/{stream_key}" + end end end diff --git a/mix.exs b/mix.exs index 9f88608..9bd519d 100644 --- a/mix.exs +++ b/mix.exs @@ -47,7 +47,8 @@ defmodule Boombox.Mixfile do github: "membraneframework/membrane_mp4_plugin", branch: "isom-avc3"}, {:membrane_realtimer_plugin, ">= 0.0.0"}, # {:membrane_rtmp_plugin, ">= 0.0.0"}, - {:membrane_rtmp_plugin, path: "../membrane_rtmp_plugin"}, + {:membrane_rtmp_plugin, + github: "membraneframework/membrane_rtmp_plugin", branch: "handle_new_client"}, {:membrane_ffmpeg_swresample_plugin, ">= 0.0.0"}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:dialyxir, ">= 0.0.0", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 1238e08..4c72b0e 100644 --- a/mix.lock +++ b/mix.lock @@ -55,7 +55,7 @@ "membrane_raw_audio_format": {:hex, :membrane_raw_audio_format, "0.12.0", "b574cd90f69ce2a8b6201b0ccf0826ca28b0fbc8245b8078d9f11cef65f7d5d5", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}, {:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "6e6c98e3622a2b9df19eab50ba65d7eb45949b1ba306fa8423df6cdb12fd0b44"}, "membrane_raw_video_format": {:hex, :membrane_raw_video_format, "0.3.0", "ba10f475e0814a6fe79602a74536b796047577c7ef5b0e33def27cd344229699", [:mix], [], "hexpm", "2f08760061c8a5386ecf04273480f10e48d25a1a40aa99476302b0bcd34ccb1c"}, "membrane_realtimer_plugin": {:hex, :membrane_realtimer_plugin, "0.9.0", "27210d5e32a5e8bfd101c41e4d8c1876e873a52cc129ebfbee4d0ccbea1cbd21", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "b2e96d62135ee57ef9a5fdea94b3a9ab1198e5ea8ee248391b89c671125d1b51"}, - "membrane_rtmp_plugin": {:hex, :membrane_rtmp_plugin, "0.23.3", "4464d14eb67b307d6f1d0f75f883c77ac7f8bd95d0213602ed908bb9abf3d27f", [:mix], [{:membrane_aac_plugin, "~> 0.18.1", [hex: :membrane_aac_plugin, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_file_plugin, "~> 0.17.0", [hex: :membrane_file_plugin, repo: "hexpm", optional: false]}, {:membrane_flv_plugin, "~> 0.12.0", [hex: :membrane_flv_plugin, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_h26x_plugin, "~> 0.10.0", [hex: :membrane_h26x_plugin, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "fa5fd0ebbbe733f0ca3613de1826aa99316a6211a98877558caa61e86db2f655"}, + "membrane_rtmp_plugin": {:git, "https://github.com/membraneframework/membrane_rtmp_plugin.git", "c3357ce2d6531ef59d27b0cc74524f6138e54ee7", [branch: "handle_new_client"]}, "membrane_rtp_format": {:hex, :membrane_rtp_format, "0.8.0", "828924bbd27efcf85b2015ae781e824c4a9928f0a7dc132abc66817b2c6edfc4", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "bc75d2a649dfaef6df563212fbb9f9f62eebc871393692f9dae8d289bd4f94bb"}, "membrane_rtp_h264_plugin": {:hex, :membrane_rtp_h264_plugin, "0.19.2", "de3eeaf35052f9f709d469fa7630d9ecc8f5787019f7072516eae1fd881bc792", [:mix], [{:bunch, "~> 1.5", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.0", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_rtp_format, "~> 0.8.0", [hex: :membrane_rtp_format, repo: "hexpm", optional: false]}], "hexpm", "d298e9cd471ab3601366c48ca0fec84135966707500152bbfcf3f968700647ae"}, "membrane_rtp_opus_plugin": {:hex, :membrane_rtp_opus_plugin, "0.9.0", "ae76421faa04697a4af76a55b6c5e675dea61b611d29d8201098783d42863af7", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_opus_format, "~> 0.3.0", [hex: :membrane_opus_format, repo: "hexpm", optional: false]}, {:membrane_rtp_format, "~> 0.8.0", [hex: :membrane_rtp_format, repo: "hexpm", optional: false]}], "hexpm", "58f095d2978daf999d87c1c016007cb7d99434208486331ab5045e77f5be9dcc"}, diff --git a/test/boombox_test.exs b/test/boombox_test.exs index 02a6f75..08a8115 100644 --- a/test/boombox_test.exs +++ b/test/boombox_test.exs @@ -103,7 +103,8 @@ defmodule BoomboxTest do @tag :rtmp_webrtc async_test "rtmp -> webrtc -> mp4", %{tmp_dir: tmp} do - url = "rtmp://localhost:5002" + url = "rtmp://localhost:5002/app/stream_key" + signaling = Membrane.WebRTC.SignalingChannel.new() t1 = From f292864bc558211cf48589a06c287149213e5e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 24 Jul 2024 14:26:05 +0200 Subject: [PATCH 4/9] url parsing --- lib/boombox/rtmp.ex | 9 ++++----- mix.lock | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/boombox/rtmp.ex b/lib/boombox/rtmp.ex index 8782f96..b58241f 100644 --- a/lib/boombox/rtmp.ex +++ b/lib/boombox/rtmp.ex @@ -4,14 +4,13 @@ defmodule Boombox.RTMP do import Membrane.ChildrenSpec require Membrane.Logger alias Boombox.Pipeline.{Ready, Wait} + alias Membrane.RTMP.Utils @type state :: %{server_pid: pid()} | nil @spec create_input(URI.t()) :: Wait.t() def create_input(uri) do - uri = URI.new!(uri) - - {target_app, target_stream_key} = get_app_stream_key_from_path(uri.path) + {use_ssl?, port, target_app, target_stream_key} = Utils.parse_url(uri) boombox = self() @@ -27,8 +26,8 @@ defmodule Boombox.RTMP do {:ok, _server} = Membrane.RTMP.Server.start_link( handler: %Membrane.RTMP.Source.ClientHandler{controlling_process: self()}, - port: uri.port, - use_ssl?: false, + port: port, + use_ssl?: use_ssl?, new_client_callback: new_client_callback, client_timeout: 1_000 ) diff --git a/mix.lock b/mix.lock index 4c72b0e..835b5fd 100644 --- a/mix.lock +++ b/mix.lock @@ -43,7 +43,7 @@ "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.17.2", "650e134c2345d946f930082fac8bac9f5aba785a7817d38a9a9da41ffc56fa92", [:mix], [{:logger_backends, "~> 1.0", [hex: :logger_backends, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "df50c6040004cd7b901cf057bd7e99c875bbbd6ae574efc93b2c753c96f43b9d"}, "membrane_flv_plugin": {:hex, :membrane_flv_plugin, "0.12.0", "d715ad405af86dcaf4b2f479e34088e1f6738c7280366828e1066b39d2aa493a", [:mix], [{:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}], "hexpm", "a317872d6d394e550c7bfd8979f12a3a1cc1e89b547d75360321025b403d3279"}, "membrane_funnel_plugin": {:hex, :membrane_funnel_plugin, "0.9.0", "9cfe09e44d65751f7d9d8d3c42e14797f7be69e793ac112ea63cd224af70a7bf", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "988790aca59d453a6115109f050699f7f45a2eb6a7f8dc5c96392760cddead54"}, - "membrane_h264_ffmpeg_plugin": {:hex, :membrane_h264_ffmpeg_plugin, "0.32.0", "6032274dc01a41fe74806480e13ebded71f4833238554bca7ef2bfb8a48d5c97", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "09f6bc3a631aadb4fa9c8c6abaf97f375b94b94a2f24332d25ed4610d4ea5635"}, + "membrane_h264_ffmpeg_plugin": {:hex, :membrane_h264_ffmpeg_plugin, "0.32.1", "1e9eb5647dd5fcfc4a35b69b6c5bdaad27e51d3f8fc0a7fe17cb02b710353cbf", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "e28aafb236587c6e093d610f3e4ee5fd6801250152f4743037b096b49e6e9a53"}, "membrane_h264_format": {:hex, :membrane_h264_format, "0.6.1", "44836cd9de0abe989b146df1e114507787efc0cf0da2368f17a10c47b4e0738c", [:mix], [], "hexpm", "4b79be56465a876d2eac2c3af99e115374bbdc03eb1dea4f696ee9a8033cd4b0"}, "membrane_h265_format": {:hex, :membrane_h265_format, "0.2.0", "1903c072cf7b0980c4d0c117ab61a2cd33e88782b696290de29570a7fab34819", [:mix], [], "hexpm", "6df418bdf242c0d9f7dbf2e5aea4c2d182e34ac9ad5a8b8cef2610c290002e83"}, "membrane_h26x_plugin": {:hex, :membrane_h26x_plugin, "0.10.2", "caf2790d8c107df35f8d456b45f4e09fb9c56ce6c7669a3a03f7d59972e6ed82", [:mix], [{:bunch, "~> 1.4", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.0", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_h265_format, "~> 0.2.0", [hex: :membrane_h265_format, repo: "hexpm", optional: false]}], "hexpm", "becf1ac4a589adecd850137ccd61a33058f686083a514a7e39fcd721bcf9fb2e"}, @@ -55,7 +55,7 @@ "membrane_raw_audio_format": {:hex, :membrane_raw_audio_format, "0.12.0", "b574cd90f69ce2a8b6201b0ccf0826ca28b0fbc8245b8078d9f11cef65f7d5d5", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}, {:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "6e6c98e3622a2b9df19eab50ba65d7eb45949b1ba306fa8423df6cdb12fd0b44"}, "membrane_raw_video_format": {:hex, :membrane_raw_video_format, "0.3.0", "ba10f475e0814a6fe79602a74536b796047577c7ef5b0e33def27cd344229699", [:mix], [], "hexpm", "2f08760061c8a5386ecf04273480f10e48d25a1a40aa99476302b0bcd34ccb1c"}, "membrane_realtimer_plugin": {:hex, :membrane_realtimer_plugin, "0.9.0", "27210d5e32a5e8bfd101c41e4d8c1876e873a52cc129ebfbee4d0ccbea1cbd21", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "b2e96d62135ee57ef9a5fdea94b3a9ab1198e5ea8ee248391b89c671125d1b51"}, - "membrane_rtmp_plugin": {:git, "https://github.com/membraneframework/membrane_rtmp_plugin.git", "c3357ce2d6531ef59d27b0cc74524f6138e54ee7", [branch: "handle_new_client"]}, + "membrane_rtmp_plugin": {:git, "https://github.com/membraneframework/membrane_rtmp_plugin.git", "ca181ea61f5b96912876b3693202c0f4ca697e8e", [branch: "handle_new_client"]}, "membrane_rtp_format": {:hex, :membrane_rtp_format, "0.8.0", "828924bbd27efcf85b2015ae781e824c4a9928f0a7dc132abc66817b2c6edfc4", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "bc75d2a649dfaef6df563212fbb9f9f62eebc871393692f9dae8d289bd4f94bb"}, "membrane_rtp_h264_plugin": {:hex, :membrane_rtp_h264_plugin, "0.19.2", "de3eeaf35052f9f709d469fa7630d9ecc8f5787019f7072516eae1fd881bc792", [:mix], [{:bunch, "~> 1.5", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.0", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_rtp_format, "~> 0.8.0", [hex: :membrane_rtp_format, repo: "hexpm", optional: false]}], "hexpm", "d298e9cd471ab3601366c48ca0fec84135966707500152bbfcf3f968700647ae"}, "membrane_rtp_opus_plugin": {:hex, :membrane_rtp_opus_plugin, "0.9.0", "ae76421faa04697a4af76a55b6c5e675dea61b611d29d8201098783d42863af7", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_opus_format, "~> 0.3.0", [hex: :membrane_opus_format, repo: "hexpm", optional: false]}, {:membrane_rtp_format, "~> 0.8.0", [hex: :membrane_rtp_format, repo: "hexpm", optional: false]}], "hexpm", "58f095d2978daf999d87c1c016007cb7d99434208486331ab5045e77f5be9dcc"}, @@ -76,7 +76,7 @@ "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, "ratio": {:hex, :ratio, "4.0.1", "3044166f2fc6890aa53d3aef0c336f84b2bebb889dc57d5f95cc540daa1912f8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "c60cbb3ccdff9ffa56e7d6d1654b5c70d9f90f4d753ab3a43a6bf40855b881ce"}, - "req": {:hex, :req, "0.5.2", "70b4976e5fbefe84e5a57fd3eea49d4e9aa0ac015301275490eafeaec380f97f", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0c63539ab4c2d6ced6114d2684276cef18ac185ee00674ee9af4b1febba1f986"}, + "req": {:hex, :req, "0.5.4", "e375e4812adf83ffcf787871d7a124d873e983e3b77466e6608b973582f7f837", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "a17998ffe2ef54f79bfdd782ef9f4cbf987d93851e89444cbc466a6a25eee494"}, "shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"}, From 60ec89840f8d4e695bcecb5d2c1cc4145a762b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 24 Jul 2024 14:37:27 +0200 Subject: [PATCH 5/9] rtmp server under utility supervisor --- lib/boombox/pipeline.ex | 4 ++-- lib/boombox/rtmp.ex | 32 +++++++++++++------------------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/lib/boombox/pipeline.ex b/lib/boombox/pipeline.ex index 6952099..e226aa7 100644 --- a/lib/boombox/pipeline.ex +++ b/lib/boombox/pipeline.ex @@ -252,8 +252,8 @@ defmodule Boombox.Pipeline do Boombox.MP4.create_input(location) end - defp create_input([:rtmp, uri], _ctx) do - Boombox.RTMP.create_input(uri) + defp create_input([:rtmp, uri], ctx) do + Boombox.RTMP.create_input(uri, ctx.utility_supervisor) end @spec create_output(Boombox.output(), Membrane.Pipeline.CallbackContext.t()) :: diff --git a/lib/boombox/rtmp.ex b/lib/boombox/rtmp.ex index b58241f..134cb44 100644 --- a/lib/boombox/rtmp.ex +++ b/lib/boombox/rtmp.ex @@ -8,8 +8,8 @@ defmodule Boombox.RTMP do @type state :: %{server_pid: pid()} | nil - @spec create_input(URI.t()) :: Wait.t() - def create_input(uri) do + @spec create_input(URI.t(), pid()) :: Wait.t() + def create_input(uri, utility_supervisor) do {use_ssl?, port, target_app, target_stream_key} = Utils.parse_url(uri) boombox = self() @@ -22,14 +22,18 @@ defmodule Boombox.RTMP do end end - # Run the standalone server + server_options = %{ + handler: %Membrane.RTMP.Source.ClientHandler{controlling_process: self()}, + port: port, + use_ssl?: use_ssl?, + new_client_callback: new_client_callback, + client_timeout: 1_000 + } + {:ok, _server} = - Membrane.RTMP.Server.start_link( - handler: %Membrane.RTMP.Source.ClientHandler{controlling_process: self()}, - port: port, - use_ssl?: use_ssl?, - new_client_callback: new_client_callback, - client_timeout: 1_000 + Membrane.UtilitySupervisor.start_link_child( + utility_supervisor, + {Membrane.RTMP.Server, server_options} ) %Wait{} @@ -51,14 +55,4 @@ defmodule Boombox.RTMP do %Ready{spec_builder: spec, track_builders: track_builders} end - - defp get_app_stream_key_from_path(path) do - case String.split(path, "/", trim: true) do - [app | [stream_key]] -> - {app, stream_key} - - _error -> - raise "Invalid RTMP URI path #{inspect(path)}, expected /{app}/{stream_key}" - end - end end From e4435cff0a82dbfe4d029b5dd68fa2b25e5a728c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 24 Jul 2024 19:36:38 +0200 Subject: [PATCH 6/9] ci fix --- .circleci/config.yml | 4 ++++ mix.lock | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c077fb4..6b43c90 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,16 +7,20 @@ workflows: build: jobs: - elixir/build_test: + cache-version: 3 filters: &filters tags: only: /v.*/ - elixir/test: + cache-version: 3 filters: <<: *filters - elixir/lint: + cache-version: 3 filters: <<: *filters - elixir/hex_publish: + cache-version: 3 requires: - elixir/build_test - elixir/test diff --git a/mix.lock b/mix.lock index 835b5fd..59c1a02 100644 --- a/mix.lock +++ b/mix.lock @@ -38,7 +38,7 @@ "membrane_aac_plugin": {:hex, :membrane_aac_plugin, "0.18.1", "30433bffd4d5d773f79448dd9afd55d77338721688f09a89b20d742a68cc2c3d", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "8fd048c47d5d2949eb557e19f43f62d534d3af5096187f1a1a3a1694d14b772c"}, "membrane_cmaf_format": {:hex, :membrane_cmaf_format, "0.7.1", "9ea858faefdcb181cdfa8001be827c35c5f854e9809ad57d7062cff1f0f703fd", [:mix], [], "hexpm", "3c7b4ed2a986e27f6f336d2f19e9442cb31d93b3142fc024c019572faca54a73"}, "membrane_common_c": {:hex, :membrane_common_c, "0.16.0", "caf3f29d2f5a1d32d8c2c122866110775866db2726e4272be58e66dfdf4bce40", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "a3c7e91de1ce1f8b23b9823188a5d13654d317235ea0ca781c05353ed3be9b1c"}, - "membrane_core": {:hex, :membrane_core, "1.1.0", "c3bbaa5af7c26a7c3748e573efe343c2104801e3463b9e491a607e82860334a4", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0 or ~> 4.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3209d7f7e86d736cb7caffbba16b075c571cebb9439ab939ed6119c50fb59a5"}, + "membrane_core": {:hex, :membrane_core, "1.1.1", "4dcff6e9f3b2ecd4f437c20e201e53957731772c0f15b3005062c41f7f58f500", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0 or ~> 4.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3802f3fc071505c59d48792487d9927e803d4edb4039710ffa52cdb60bb0aecc"}, "membrane_ffmpeg_swresample_plugin": {:hex, :membrane_ffmpeg_swresample_plugin, "0.20.2", "2e669f0b25418d10b51a73bc52d2e12e4a3a26b416c5c1199d852c3f781a18b3", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.2", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_audio_format, "~> 0.12.0", [hex: :membrane_raw_audio_format, repo: "hexpm", optional: false]}, {:mockery, "~> 2.1", [hex: :mockery, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "6c8d3bcd61d568dd94cabb9b45f29e8926e0076e4432d8f419378e004e02147c"}, "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.17.2", "650e134c2345d946f930082fac8bac9f5aba785a7817d38a9a9da41ffc56fa92", [:mix], [{:logger_backends, "~> 1.0", [hex: :logger_backends, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "df50c6040004cd7b901cf057bd7e99c875bbbd6ae574efc93b2c753c96f43b9d"}, "membrane_flv_plugin": {:hex, :membrane_flv_plugin, "0.12.0", "d715ad405af86dcaf4b2f479e34088e1f6738c7280366828e1066b39d2aa493a", [:mix], [{:membrane_aac_format, "~> 0.8.0", [hex: :membrane_aac_format, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.1", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}], "hexpm", "a317872d6d394e550c7bfd8979f12a3a1cc1e89b547d75360321025b403d3279"}, @@ -55,7 +55,7 @@ "membrane_raw_audio_format": {:hex, :membrane_raw_audio_format, "0.12.0", "b574cd90f69ce2a8b6201b0ccf0826ca28b0fbc8245b8078d9f11cef65f7d5d5", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}, {:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "6e6c98e3622a2b9df19eab50ba65d7eb45949b1ba306fa8423df6cdb12fd0b44"}, "membrane_raw_video_format": {:hex, :membrane_raw_video_format, "0.3.0", "ba10f475e0814a6fe79602a74536b796047577c7ef5b0e33def27cd344229699", [:mix], [], "hexpm", "2f08760061c8a5386ecf04273480f10e48d25a1a40aa99476302b0bcd34ccb1c"}, "membrane_realtimer_plugin": {:hex, :membrane_realtimer_plugin, "0.9.0", "27210d5e32a5e8bfd101c41e4d8c1876e873a52cc129ebfbee4d0ccbea1cbd21", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "b2e96d62135ee57ef9a5fdea94b3a9ab1198e5ea8ee248391b89c671125d1b51"}, - "membrane_rtmp_plugin": {:git, "https://github.com/membraneframework/membrane_rtmp_plugin.git", "ca181ea61f5b96912876b3693202c0f4ca697e8e", [branch: "handle_new_client"]}, + "membrane_rtmp_plugin": {:git, "https://github.com/membraneframework/membrane_rtmp_plugin.git", "81d30d9f67b12fb288af489576ad2309775d4247", [branch: "handle_new_client"]}, "membrane_rtp_format": {:hex, :membrane_rtp_format, "0.8.0", "828924bbd27efcf85b2015ae781e824c4a9928f0a7dc132abc66817b2c6edfc4", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "bc75d2a649dfaef6df563212fbb9f9f62eebc871393692f9dae8d289bd4f94bb"}, "membrane_rtp_h264_plugin": {:hex, :membrane_rtp_h264_plugin, "0.19.2", "de3eeaf35052f9f709d469fa7630d9ecc8f5787019f7072516eae1fd881bc792", [:mix], [{:bunch, "~> 1.5", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.0", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_rtp_format, "~> 0.8.0", [hex: :membrane_rtp_format, repo: "hexpm", optional: false]}], "hexpm", "d298e9cd471ab3601366c48ca0fec84135966707500152bbfcf3f968700647ae"}, "membrane_rtp_opus_plugin": {:hex, :membrane_rtp_opus_plugin, "0.9.0", "ae76421faa04697a4af76a55b6c5e675dea61b611d29d8201098783d42863af7", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_opus_format, "~> 0.3.0", [hex: :membrane_opus_format, repo: "hexpm", optional: false]}, {:membrane_rtp_format, "~> 0.8.0", [hex: :membrane_rtp_format, repo: "hexpm", optional: false]}], "hexpm", "58f095d2978daf999d87c1c016007cb7d99434208486331ab5045e77f5be9dcc"}, From 08a557d90ca025125a668fc75bad65c1f4e94953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 24 Jul 2024 19:53:52 +0200 Subject: [PATCH 7/9] dialyzer fix --- lib/boombox/rtmp.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/boombox/rtmp.ex b/lib/boombox/rtmp.ex index 134cb44..0e9d22e 100644 --- a/lib/boombox/rtmp.ex +++ b/lib/boombox/rtmp.ex @@ -8,7 +8,7 @@ defmodule Boombox.RTMP do @type state :: %{server_pid: pid()} | nil - @spec create_input(URI.t(), pid()) :: Wait.t() + @spec create_input(String.t(), pid()) :: Wait.t() def create_input(uri, utility_supervisor) do {use_ssl?, port, target_app, target_stream_key} = Utils.parse_url(uri) From 7401a917959947ed8a8370e753ef8b5e4b9c48e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 31 Jul 2024 03:30:11 +0200 Subject: [PATCH 8/9] small fixes --- lib/boombox/rtmp.ex | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/boombox/rtmp.ex b/lib/boombox/rtmp.ex index 0e9d22e..6577ee9 100644 --- a/lib/boombox/rtmp.ex +++ b/lib/boombox/rtmp.ex @@ -4,13 +4,11 @@ defmodule Boombox.RTMP do import Membrane.ChildrenSpec require Membrane.Logger alias Boombox.Pipeline.{Ready, Wait} - alias Membrane.RTMP.Utils - - @type state :: %{server_pid: pid()} | nil + alias Membrane.RTMP @spec create_input(String.t(), pid()) :: Wait.t() def create_input(uri, utility_supervisor) do - {use_ssl?, port, target_app, target_stream_key} = Utils.parse_url(uri) + {use_ssl?, port, target_app, target_stream_key} = RTMP.Utils.parse_url(uri) boombox = self() From 64d9955ddcabd9f4620a9a7a0255e4f6d0be5a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Chali=C5=84ski?= Date: Wed, 31 Jul 2024 03:46:18 +0200 Subject: [PATCH 9/9] lint fix --- lib/boombox/pipeline.ex | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/boombox/pipeline.ex b/lib/boombox/pipeline.ex index e226aa7..fd2c9a8 100644 --- a/lib/boombox/pipeline.ex +++ b/lib/boombox/pipeline.ex @@ -58,8 +58,7 @@ defmodule Boombox.Pipeline do spec_builder: [], track_builders: nil, last_result: nil, - eos_info: nil, - rtmp_input_state: nil + eos_info: nil ] @typedoc """ @@ -87,8 +86,7 @@ defmodule Boombox.Pipeline do spec_builder: Membrane.ChildrenSpec.t(), track_builders: Boombox.Pipeline.track_builders() | nil, last_result: Boombox.Pipeline.Ready.t() | Boombox.Pipeline.Wait.t() | nil, - eos_info: term(), - rtmp_input_state: Boombox.RTMP.state() + eos_info: term() } end