11defmodule Membrane.Demo.RTSPToHLS.Pipeline do
22 @ moduledoc """
3- The pipeline, which converts the RTP stream to HLS.
3+ The pipeline which converts the stream to HLS.
44 """
55 use Membrane.Pipeline
66
77 require Logger
88
99 @ impl true
1010 def handle_init ( _context , options ) do
11- Logger . debug ( "Source handle_init options: #{ inspect ( options ) } " )
12-
1311 spec = [
1412 child ( :source , % Membrane.RTSP.Source {
1513 transport: { :udp , options . port , options . port + 5 } ,
1614 allowed_media_types: [ :video , :audio ] ,
1715 stream_uri: options . stream_url ,
1816 on_connection_closed: :send_eos
17+ } ) ,
18+ child ( :hls , % Membrane.HTTPAdaptiveStream.SinkBin {
19+ target_window_duration: Membrane.Time . seconds ( 120 ) ,
20+ manifest_module: Membrane.HTTPAdaptiveStream.HLS ,
21+ storage: % Membrane.HTTPAdaptiveStream.Storages.FileStorage {
22+ directory: options . output_path
23+ }
1924 } )
2025 ]
2126
22- { [ spec: spec ] ,
23- % {
24- output_path: options . output_path ,
25- parent_pid: options . parent_pid ,
26- tracks_left_to_link: nil ,
27- track_specs: [ ]
28- } }
27+ { [ spec: spec ] , % { parent_pid: options . parent_pid } }
2928 end
3029
3130 @ impl true
3231 def handle_child_notification ( { :set_up_tracks , tracks } , :source , _ctx , state ) do
33- tracks_left_to_link =
34- [ :audio , :video ]
35- |> Enum . filter ( fn media_type -> Enum . any? ( tracks , & ( & 1 . type == media_type ) ) end )
36-
37- { [ ] , % { state | tracks_left_to_link: tracks_left_to_link } }
38- end
39-
40- @ impl true
41- def handle_child_notification ( { :new_track , ssrc , track } , :source , _ctx , state ) do
42- if track . type in state . tracks_left_to_link do
43- tracks_left_to_link = List . delete ( state . tracks_left_to_link , track . type )
44- track_specs = [ get_track_spec ( ssrc , track ) | state . track_specs ]
45-
46- spec_action =
47- if tracks_left_to_link == [ ] do
48- hls =
49- child ( :hls , % Membrane.HTTPAdaptiveStream.SinkBin {
50- target_window_duration: Membrane.Time . seconds ( 120 ) ,
51- manifest_module: Membrane.HTTPAdaptiveStream.HLS ,
52- storage: % Membrane.HTTPAdaptiveStream.Storages.FileStorage {
53- directory: state . output_path
54- }
55- } )
32+ track_specs =
33+ Enum . uniq_by ( tracks , & & 1 . type )
34+ |> Enum . filter ( & ( & 1 . type in [ :audio , :video ] ) )
35+ |> Enum . map ( fn track ->
36+ encoding =
37+ case track do
38+ % { type: :audio } -> :AAC
39+ % { type: :video } -> :H264
40+ end
5641
57- [ spec: [ hls | track_specs ] ]
58- else
59- [ ]
60- end
61-
62- { spec_action , % { state | track_specs: track_specs , tracks_left_to_link: tracks_left_to_link } }
63- else
64- Logger . warning ( "Unsupported stream connected" )
65-
66- spec =
6742 get_child ( :source )
68- |> via_out ( Pad . ref ( :output , ssrc ) )
69- |> child ( { :fake_sink , ssrc } , Membrane.Debug.Sink )
70-
71- { [ spec: spec ] , state }
72- end
43+ |> via_out ( Pad . ref ( :output , track . control_path ) )
44+ |> via_in ( :input ,
45+ options: [ encoding: encoding , segment_duration: Membrane.Time . seconds ( 4 ) ]
46+ )
47+ |> get_child ( :hls )
48+ end )
49+
50+ { [ spec: track_specs ] , state }
7351 end
7452
7553 @ impl true
@@ -79,22 +57,8 @@ defmodule Membrane.Demo.RTSPToHLS.Pipeline do
7957 end
8058
8159 @ impl true
82- def handle_child_notification ( _notification , _element , _ctx , state ) do
60+ def handle_child_notification ( notification , _element , _ctx , state ) do
61+ Logger . warning ( "Ignoring notification #{ notification } " )
8362 { [ ] , state }
8463 end
85-
86- defp get_track_spec ( ssrc , track ) do
87- encoding =
88- case track do
89- % { type: :audio } -> :AAC
90- % { type: :video } -> :H264
91- end
92-
93- get_child ( :source )
94- |> via_out ( Pad . ref ( :output , ssrc ) )
95- |> via_in ( :input ,
96- options: [ encoding: encoding , segment_duration: Membrane.Time . seconds ( 4 ) ]
97- )
98- |> get_child ( :hls )
99- end
10064end
0 commit comments