@@ -5,10 +5,8 @@ defmodule Shinkai.Sources.RTSP do
55
66 require Logger
77
8- import Shinkai.Utils
9-
10- alias MediaCodecs.MPEG4
11- alias Shinkai . { Sources , Track }
8+ alias Shinkai.Sources
9+ alias Shinkai.Sources.RTSP.MediaProcessor
1210
1311 @ timeout 6_000
1412 @ reconnect_timeout 5_000
@@ -33,7 +31,7 @@ defmodule Shinkai.Sources.RTSP do
3331 id: source . id ,
3432 rtsp_pid: pid ,
3533 tracks: % { } ,
36- packets_topic: packets_topic ( source . id )
34+ media_processor: nil
3735 }
3836
3937 { :ok , state , { :continue , :connect } }
@@ -46,21 +44,15 @@ defmodule Shinkai.Sources.RTSP do
4644 def handle_info ( :reconnect , state ) , do: do_connect ( state )
4745
4846 def handle_info ( { :rtsp , _pid , { id , sample_or_samples } } , state ) do
49- :ok =
50- Phoenix.PubSub . broadcast (
51- Shinkai.PubSub ,
52- state . packets_topic ,
53- { :packet , to_packets ( sample_or_samples , state . tracks [ id ] . id ) }
54- )
55-
56- { :noreply , state }
47+ media_processor = MediaProcessor . handle_sample ( id , sample_or_samples , state . media_processor )
48+ { :noreply , % { state | media_processor: media_processor } }
5749 end
5850
5951 @ impl true
6052 def handle_info ( { :rtsp , pid , :session_closed } , % { rtsp_pid: pid } = state ) do
6153 Logger . error ( "[#{ state . id } ] rtsp client disconnected" )
62- Phoenix.PubSub . broadcast! ( Shinkai.PubSub , state_topic ( state . id ) , :disconnected )
63- Sources . update_source_status ( state . id , :failed )
54+ Phoenix.PubSub . broadcast! ( Shinkai.PubSub , Shinkai.Utils . state_topic ( state . id ) , :disconnected )
55+ update_status ( state , :failed )
6456 Process . send_after ( self ( ) , :reconnect , @ reconnect_timeout )
6557 { :noreply , state }
6658 end
@@ -73,21 +65,10 @@ defmodule Shinkai.Sources.RTSP do
7365
7466 defp do_connect ( state ) do
7567 with { :ok , tracks } <- RTSP . connect ( state . rtsp_pid , @ timeout ) ,
76- tracks <- build_tracks ( tracks ) ,
7768 :ok <- RTSP . play ( state . rtsp_pid ) do
78- codecs = tracks |> Map . values ( ) |> Enum . map_join ( ", " , & & 1 . codec )
79- Logger . info ( "[#{ state . id } ] start reading from #{ map_size ( tracks ) } tracks (#{ codecs } )" )
80-
8169 update_status ( state , :streaming )
82-
83- :ok =
84- Phoenix.PubSub . broadcast (
85- Shinkai.PubSub ,
86- tracks_topic ( state . id ) ,
87- { :tracks , Map . values ( tracks ) }
88- )
89-
90- { :noreply , % { state | tracks: tracks } }
70+ media_processor = MediaProcessor . new ( state . id , tracks )
71+ { :noreply , % { state | media_processor: media_processor } }
9172 else
9273 { :error , reason } ->
9374 Logger . error ( "[#{ state . id } ] rtsp connection failed: #{ inspect ( reason ) } " )
@@ -97,49 +78,5 @@ defmodule Shinkai.Sources.RTSP do
9778 end
9879 end
9980
100- defp build_tracks ( tracks ) do
101- tracks
102- |> Enum . with_index ( 1 )
103- |> Map . new ( fn { track , id } ->
104- codec = codec ( String . downcase ( track . rtpmap . encoding ) )
105-
106- { track . control_path ,
107- Track . new (
108- id: id ,
109- type: track . type ,
110- codec: codec ,
111- timescale: track . rtpmap . clock_rate ,
112- priv_data: priv_data ( codec , track . fmtp )
113- ) }
114- end )
115- end
116-
117- defp codec ( "mpeg4-generic" ) , do: :aac
118- defp codec ( other ) , do: String . to_atom ( other )
119-
120- defp priv_data ( :aac , fmtp ) , do: MPEG4.AudioSpecificConfig . parse ( fmtp . config )
121- defp priv_data ( :h264 , % { sprop_parameter_sets: nil } ) , do: nil
122- defp priv_data ( :h264 , % { sprop_parameter_sets: pps } ) , do: { pps . sps , [ pps . pps ] }
123- defp priv_data ( :h265 , % { sprop_vps: nil } ) , do: nil
124- defp priv_data ( :h265 , fmtp ) , do: { hd ( fmtp . sprop_vps ) , hd ( fmtp . sprop_sps ) , fmtp . sprop_pps }
125- defp priv_data ( _codec , _fmtp ) , do: nil
126-
127- defp to_packets ( samples , track_id ) when is_list ( samples ) do
128- Enum . map ( samples , & packet_from_sample ( track_id , & 1 ) )
129- end
130-
131- defp to_packets ( sample , track_id ) , do: packet_from_sample ( track_id , sample )
132-
133- defp packet_from_sample ( track_id , { payload , pts , sync? , _timestamp } ) do
134- Shinkai.Packet . new ( payload ,
135- track_id: track_id ,
136- dts: pts ,
137- pts: pts ,
138- sync?: sync?
139- )
140- end
141-
142- defp update_status ( state , status ) do
143- Sources . update_source_status ( state . id , status )
144- end
81+ defp update_status ( state , status ) , do: Sources . update_source_status ( state . id , status )
14582end
0 commit comments