Skip to content

Commit 4b6cb9a

Browse files
committed
SourceBin dynamic pads
1 parent 89309aa commit 4b6cb9a

File tree

3 files changed

+96
-20
lines changed

3 files changed

+96
-20
lines changed

lib/membrane_rtmp_plugin/rtmp/source/bin.ex

+93-20
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ defmodule Membrane.RTMP.SourceBin do
2424

2525
def_output_pad :video,
2626
accepted_format: H264,
27-
availability: :always
27+
availability: :on_request
2828

2929
def_output_pad :audio,
3030
accepted_format: AAC,
31-
availability: :always
31+
availability: :on_request
3232

3333
def_options socket: [
3434
spec: :gen_tcp.socket() | :ssl.sslsocket(),
@@ -57,34 +57,101 @@ defmodule Membrane.RTMP.SourceBin do
5757

5858
@impl true
5959
def handle_init(_ctx, %__MODULE__{} = opts) do
60-
structure = [
60+
spec = [
6161
child(:src, %RTMP.Source{
6262
socket: opts.socket,
6363
validator: opts.validator,
6464
use_ssl?: opts.use_ssl?
6565
})
66-
|> child(:demuxer, Membrane.FLV.Demuxer),
67-
#
68-
child(:audio_parser, %Membrane.AAC.Parser{
69-
out_encapsulation: :none
70-
}),
71-
child(:video_parser, Membrane.H264.Parser),
72-
#
73-
get_child(:demuxer)
74-
|> via_out(Pad.ref(:audio, 0))
75-
|> get_child(:audio_parser)
76-
|> bin_output(:audio),
77-
#
78-
get_child(:demuxer)
79-
|> via_out(Pad.ref(:video, 0))
80-
|> get_child(:video_parser)
81-
|> bin_output(:video)
66+
|> child(:demuxer, Membrane.FLV.Demuxer)
8267
]
8368

84-
{[spec: structure], %{}}
69+
state = %{
70+
demuxer_audio_pad_ref: nil,
71+
demuxer_video_pad_ref: nil
72+
}
73+
74+
{[spec: spec], state}
75+
end
76+
77+
@impl true
78+
def handle_pad_added(Pad.ref(:audio, _ref) = pad, _ctx, state) do
79+
spec =
80+
if state.demuxer_audio_pad_ref != nil do
81+
[
82+
get_child(:demuxer)
83+
|> via_out(state.demuxer_audio_pad_ref)
84+
|> child(:audio_parser, %Membrane.AAC.Parser{
85+
out_encapsulation: :none
86+
})
87+
|> bin_output(pad)
88+
]
89+
else
90+
[
91+
child(:funnel_audio, Membrane.Funnel)
92+
|> bin_output(pad)
93+
]
94+
end
95+
96+
{[spec: spec], state}
97+
end
98+
99+
def handle_pad_added(Pad.ref(:video, _ref) = pad, _ctx, state) do
100+
spec =
101+
if state.demuxer_video_pad_ref != nil do
102+
[
103+
get_child(:demuxer)
104+
|> via_out(state.demuxer_video_pad_ref)
105+
|> child(:video_parser, Membrane.H264.Parser)
106+
|> bin_output(pad)
107+
]
108+
else
109+
[
110+
child(:funnel_video, Membrane.Funnel)
111+
|> bin_output(pad)
112+
]
113+
end
114+
115+
{[spec: spec], state}
85116
end
86117

87118
@impl true
119+
def handle_child_notification({:new_stream, pad_ref, :AAC}, :demuxer, ctx, state) do
120+
audio_pad_ref = get_pad(:audio, ctx)
121+
122+
if audio_pad_ref != nil do
123+
{[
124+
spec: [
125+
get_child(:demuxer)
126+
|> via_out(pad_ref)
127+
|> child(:audio_parser, %Membrane.AAC.Parser{
128+
out_encapsulation: :none
129+
})
130+
|> get_child(:funnel_audio)
131+
]
132+
], state}
133+
else
134+
{[], %{state | demuxer_audio_pad_ref: pad_ref}}
135+
end
136+
end
137+
138+
def handle_child_notification({:new_stream, pad_ref, :H264}, :demuxer, ctx, state) do
139+
video_pad_ref = get_pad(:video, ctx)
140+
141+
if video_pad_ref != nil do
142+
{[
143+
spec: [
144+
get_child(:demuxer)
145+
|> via_out(pad_ref)
146+
|> child(:video_parser, Membrane.H264.Parser)
147+
|> get_child(:funnel_video)
148+
]
149+
], state}
150+
else
151+
{[], %{state | demuxer_video_pad_ref: pad_ref}}
152+
end
153+
end
154+
88155
def handle_child_notification(
89156
{type, _socket, _pid} = notification,
90157
:src,
@@ -128,4 +195,10 @@ defmodule Membrane.RTMP.SourceBin do
128195
def secure_pass_control(socket, source) do
129196
:ssl.controlling_process(socket, source)
130197
end
198+
199+
defp get_pad(name, ctx) do
200+
ctx.pads
201+
|> Map.keys()
202+
|> Enum.find(fn pad_ref -> Pad.name_by_ref(pad_ref) == name end)
203+
end
131204
end

mix.exs

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ defmodule Membrane.RTMP.Mixfile do
4646
{:membrane_aac_plugin, "~> 0.18.1"},
4747
{:membrane_flv_plugin, "~> 0.12.0"},
4848
{:membrane_file_plugin, "~> 0.17.0"},
49+
{:membrane_funnel_plugin, "~> 0.9.0"},
4950
# testing
5051
{:membrane_hackney_plugin, "~> 0.11.0", only: :test},
5152
{:ffmpex, "~> 0.10.0", only: :test},

mix.lock

+2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
"membrane_aac_format": {:hex, :membrane_aac_format, "0.8.0", "515631eabd6e584e0e9af2cea80471fee6246484dbbefc4726c1d93ece8e0838", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}], "hexpm", "a30176a94491033ed32be45e51d509fc70a5ee6e751f12fd6c0d60bd637013f6"},
2828
"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"},
2929
"membrane_core": {:hex, :membrane_core, "1.0.1", "08aa546c0d131c66f8b906b3dfb2b8f2749b56859f6fc52bd3ac846b944b3baa", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a35ed68561bdf0a2dbb2f994333be78cf4e1c4d734e4cd927d77d92049bb1273"},
30+
"membrane_fake_plugin": {:hex, :membrane_fake_plugin, "0.11.0", "3a2d26f15ad4940a4d44cee3354dff38fa9a39963e9b2dcb49802e150ff9a9dc", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "7c6b6a06eaa4e820d1e4836510ddb4bcb386c8918d0b37542a21caf6b87cbe72"},
3031
"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"},
3132
"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"},
33+
"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"},
3234
"membrane_h264_format": {:hex, :membrane_h264_format, "0.6.1", "44836cd9de0abe989b146df1e114507787efc0cf0da2368f17a10c47b4e0738c", [:mix], [], "hexpm", "4b79be56465a876d2eac2c3af99e115374bbdc03eb1dea4f696ee9a8033cd4b0"},
3335
"membrane_h265_format": {:hex, :membrane_h265_format, "0.2.0", "1903c072cf7b0980c4d0c117ab61a2cd33e88782b696290de29570a7fab34819", [:mix], [], "hexpm", "6df418bdf242c0d9f7dbf2e5aea4c2d182e34ac9ad5a8b8cef2610c290002e83"},
3436
"membrane_h26x_plugin": {:hex, :membrane_h26x_plugin, "0.10.0", "0a7c6b9a7678e8c111b22b5417465ac31cf6e598cff6a53ab53a9c379bdfa1ef", [: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", "e9cde8c8995ace9fc26355037cbcc780f1727a3f63d36c21b52232fd29d0ad40"},

0 commit comments

Comments
 (0)