@@ -2,6 +2,7 @@ defmodule ExWebRTC.RTP.Munger do
22 @ moduledoc """
33 RTP Munger allows for converting RTP packet timestamps and sequence numbers
44 to a common domain.
5+ It also rewrites parts of the RTP payload that may require a similar behaviour.
56
67 This is useful when e.g. changing between Simulcast layers - the sender sends
78 three separate RTP streams (also called layers or encodings), but the receiver can receive only a
@@ -12,7 +13,7 @@ defmodule ExWebRTC.RTP.Munger do
1213 # and this is a GenServer
1314
1415 def init() do
15- {:ok, %{munger: Munger.new(90_000), layer: "h"}}
16+ {:ok, %{munger: Munger.new(:h264, 90_000), layer: "h"}}
1617 end
1718
1819 def handle_info({:ex_webrtc, _from, {:rtp, _id, rid, packet}}, state) do
@@ -34,6 +35,8 @@ defmodule ExWebRTC.RTP.Munger do
3435 """
3536
3637 alias ExRTP.Packet
38+ alias ExWebRTC.RTPCodecParameters
39+ alias ExWebRTC.RTP.VP8
3740
3841 @ max_rtp_ts 0xFFFFFFFF
3942 @ max_rtp_sn 0xFFFF
@@ -47,14 +50,16 @@ defmodule ExWebRTC.RTP.Munger do
4750 # * `sn_offset` - offset for sequence numbers
4851 # * `ts_offset` - offset for timestamps
4952 # * `update?` - flag telling if the next munged packets belongs to a new encoding
53+ # * `vp8_munger` - VP8 munger, only used when RTP packets contain VP8 codec
5054 @ opaque t ( ) :: % __MODULE__ {
5155 clock_rate: non_neg_integer ( ) ,
5256 rtp_sn: non_neg_integer ( ) | nil ,
5357 rtp_ts: non_neg_integer ( ) | nil ,
5458 wc_ts: integer ( ) | nil ,
5559 sn_offset: integer ( ) ,
5660 ts_offset: integer ( ) ,
57- update?: boolean ( )
61+ update?: boolean ( ) ,
62+ vp8_munger: VP8.Munger . t ( ) | nil
5863 }
5964
6065 @ enforce_keys [ :clock_rate ]
@@ -64,19 +69,31 @@ defmodule ExWebRTC.RTP.Munger do
6469 :wc_ts ,
6570 sn_offset: 0 ,
6671 ts_offset: 0 ,
67- update?: false
72+ update?: false ,
73+ vp8_munger: nil
6874 ] ++ @ enforce_keys
6975
7076 @ doc """
7177 Creates a new `t:ExWebRTC.RTP.Munger.t/0`.
7278
7379 `clock_rate` is the clock rate of the codec carried in munged RTP packets.
7480 """
75- @ spec new ( non_neg_integer ( ) ) :: t ( )
76- def new ( clock_rate ) do
81+ @ spec new ( :h264 | :vp8 | RTPCodecParameters . t ( ) , non_neg_integer ( ) ) :: t ( )
82+ def new ( :h264 , clock_rate ) do
7783 % __MODULE__ { clock_rate: clock_rate }
7884 end
7985
86+ def new ( :vp8 , clock_rate ) do
87+ % __MODULE__ { clock_rate: clock_rate , vp8_munger: VP8.Munger . new ( ) }
88+ end
89+
90+ def new ( % RTPCodecParameters { } = codec_params ) do
91+ case codec_params . mime_type do
92+ "video/H264" -> new ( :h264 , codec_params . clock_rate )
93+ "video/VP8" -> new ( :vp8 , codec_params . clock_rate )
94+ end
95+ end
96+
8097 @ doc """
8198 Informs the munger that the next packet passed to `munge/2` will come
8299 from a different RTP stream.
@@ -90,17 +107,30 @@ defmodule ExWebRTC.RTP.Munger do
90107 @ spec munge ( t ( ) , Packet . t ( ) ) :: { Packet . t ( ) , t ( ) }
91108 def munge ( % { rtp_sn: nil } = munger , packet ) do
92109 # first packet ever munged
110+ vp8_munger = munger . vp8_munger && VP8.Munger . init ( munger . vp8_munger , packet . payload )
111+
93112 munger = % __MODULE__ {
94113 munger
95114 | rtp_sn: packet . sequence_number ,
96115 rtp_ts: packet . timestamp ,
97- wc_ts: get_wc_ts ( packet )
116+ wc_ts: get_wc_ts ( packet ) ,
117+ vp8_munger: vp8_munger
98118 }
99119
100120 { packet , munger }
101121 end
102122
103123 def munge ( munger , packet ) when munger . update? do
124+ { vp8_munger , rtp_payload } =
125+ if munger . vp8_munger do
126+ vp8_munger = VP8.Munger . update ( munger . vp8_munger , packet . payload )
127+ VP8.Munger . munge ( vp8_munger , packet . payload )
128+ else
129+ { munger . vp8_munger , packet . payload }
130+ end
131+
132+ packet = % ExRTP.Packet { packet | payload: rtp_payload }
133+
104134 wc_ts = get_wc_ts ( packet )
105135
106136 native_in_sec = System . convert_time_unit ( 1 , :second , :native )
@@ -124,7 +154,8 @@ defmodule ExWebRTC.RTP.Munger do
124154 | rtp_sn: new_packet . sequence_number ,
125155 rtp_ts: new_packet . timestamp ,
126156 wc_ts: wc_ts ,
127- update?: false
157+ update?: false ,
158+ vp8_munger: vp8_munger
128159 }
129160
130161 { new_packet , munger }
@@ -135,6 +166,15 @@ defmodule ExWebRTC.RTP.Munger do
135166 # the first packet after the encoding update
136167 # as these might conflict with packets from the previous layer
137168 # and we should change on a keyframe anyways
169+ { vp8_munger , rtp_payload } =
170+ if munger . vp8_munger do
171+ VP8.Munger . munge ( munger . vp8_munger , packet . payload )
172+ else
173+ { munger . vp8_munger , packet . payload }
174+ end
175+
176+ packet = % ExRTP.Packet { packet | payload: rtp_payload }
177+
138178 wc_ts = get_wc_ts ( packet )
139179
140180 new_packet = adjust_packet ( munger , packet )
@@ -148,10 +188,11 @@ defmodule ExWebRTC.RTP.Munger do
148188 munger
149189 | rtp_sn: new_packet . sequence_number ,
150190 rtp_ts: new_packet . timestamp ,
151- wc_ts: wc_ts
191+ wc_ts: wc_ts ,
192+ vp8_munger: vp8_munger
152193 }
153194 else
154- munger
195+ % __MODULE__ { munger | vp8_munger: vp8_munger }
155196 end
156197
157198 { new_packet , munger }
0 commit comments