Skip to content

Commit

Permalink
[RTC-190] Add support for sprop-parameter-sets (#31)
Browse files Browse the repository at this point in the history
* [RTC-190] Add support for sprop-parameter-sets
* Fixes after review
  • Loading branch information
sgfn authored Mar 27, 2023
1 parent f62c0bb commit 900ee4c
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
15 changes: 14 additions & 1 deletion lib/ex_sdp/attribute/fmtp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ defmodule ExSDP.Attribute.FMTP do
:max_fs,
:max_dpb,
:max_br,
:sprop_parameter_sets,
# OPUS
:maxaveragebitrate,
:maxplaybackrate,
Expand Down Expand Up @@ -64,6 +65,7 @@ defmodule ExSDP.Attribute.FMTP do
max_br: non_neg_integer() | nil,
level_asymmetry_allowed: boolean() | nil,
packetization_mode: non_neg_integer() | nil,
sprop_parameter_sets: %{sps: binary(), pps: binary()} | nil,
# OPUS
maxaveragebitrate: non_neg_integer() | nil,
maxplaybackrate: non_neg_integer() | nil,
Expand Down Expand Up @@ -100,7 +102,12 @@ defmodule ExSDP.Attribute.FMTP do
Reason of parsing failure.
"""
@type reason ::
:invalid_fmtp | :invalid_pt | :string_nan | :string_not_hex | :string_not_0_nor_1
:invalid_fmtp
| :invalid_pt
| :invalid_sprop_parameter_sets
| :string_nan
| :string_not_hex
| :string_not_0_nor_1

@spec parse(binary()) :: {:ok, t()} | {:error, reason()}
def parse(fmtp) do
Expand Down Expand Up @@ -141,6 +148,11 @@ defmodule ExSDP.Attribute.FMTP do
do: {rest, %{fmtp | packetization_mode: value}}
end

defp parse_param(["sprop-parameter-sets=" <> sprop_parameter_sets | rest], fmtp) do
with {:ok, value} <- Utils.parse_sprop_parameter_sets(sprop_parameter_sets),
do: {rest, %{fmtp | sprop_parameter_sets: value}}
end

defp parse_param(["max-mbps=" <> max_mbps | rest], fmtp) do
with {:ok, value} <- Utils.parse_numeric_string(max_mbps),
do: {rest, %{fmtp | max_mbps: value}}
Expand Down Expand Up @@ -306,6 +318,7 @@ defimpl String.Chars, for: ExSDP.Attribute.FMTP do
Serializer.maybe_serialize("max-br", fmtp.max_br),
Serializer.maybe_serialize("level-asymmetry-allowed", fmtp.level_asymmetry_allowed),
Serializer.maybe_serialize("packetization-mode", fmtp.packetization_mode),
Serializer.maybe_serialize("sprop-parameter-sets", fmtp.sprop_parameter_sets),
# OPUS
Serializer.maybe_serialize("maxaveragebitrate", fmtp.maxaveragebitrate),
Serializer.maybe_serialize("maxplaybackrate", fmtp.maxplaybackrate),
Expand Down
4 changes: 4 additions & 0 deletions lib/ex_sdp/serializer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ defmodule ExSDP.Serializer do
def maybe_serialize(type, true), do: "#{type}=1"
def maybe_serialize(type, false), do: "#{type}=0"
def maybe_serialize("dtmf-tones", value), do: "#{value}"

def maybe_serialize("sprop-parameter-sets", %{sps: sps, pps: pps}),
do: "sprop-parameter-sets=#{Base.encode64(sps)},#{Base.encode64(pps)}"

def maybe_serialize(type, {key, value}), do: "#{type}=#{key}:#{value}"
def maybe_serialize(type, value), do: "#{type}=#{value}"

Expand Down
23 changes: 23 additions & 0 deletions lib/ex_sdp/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,27 @@ defmodule ExSDP.Utils do
_string_not_0_nor_1 -> {:error, :string_not_0_nor_1}
end
end

@spec parse_sprop_parameter_sets(binary) ::
{:error, :invalid_sprop_parameter_sets} | {:ok, %{sps: binary, pps: binary}}
def parse_sprop_parameter_sets(string) do
result =
String.split(string, ",", parts: 2)
|> Enum.zip([:sps, :pps])
|> Map.new(fn {encoded, type} ->
decoded =
case Base.decode64(encoded) do
{:ok, decoded} -> decoded
:error -> nil
end

{type, decoded}
end)

if Map.get(result, :sps) && Map.get(result, :pps) do
{:ok, result}
else
{:error, :invalid_sprop_parameter_sets}
end
end
end
37 changes: 37 additions & 0 deletions test/ex_sdp/attribute/fmtp_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ defmodule ExSDP.Attribute.FMTPTest do
assert {:ok, expected} == FMTP.parse(fmtp)
end

test "parses fmtp with sprop-parameter-sets parameters" do
fmtp =
"105 profile-level-id=64001f; packetization-mode=1; " <>
"sprop-parameter-sets=Z2QAH62EAQwgCGEAQwgCGEAQwgCEO1AoAt03AQEBQAAA+gAAOpgh,aO4xshs="

expected = %FMTP{
pt: 105,
profile_level_id: 0x64001F,
packetization_mode: 1,
sprop_parameter_sets: %{
sps:
<<103, 100, 0, 31, 173, 132, 1, 12, 32, 8, 97, 0, 67, 8, 2, 24, 64, 16, 194, 0, 132,
59, 80, 40, 2, 221, 55, 1, 1, 1, 64, 0, 0, 250, 0, 0, 58, 152, 33>>,
pps: <<104, 238, 49, 178, 27>>
}
}

assert {:ok, expected} == FMTP.parse(fmtp)
end

test "returns an error when DTMF tone is too big" do
fmtp = "100 0-15,256"
assert {:error, :invalid_dtmf_tones} = FMTP.parse(fmtp)
Expand Down Expand Up @@ -139,5 +159,22 @@ defmodule ExSDP.Attribute.FMTPTest do

assert "#{fmtp}" == expected
end

test "serializes FMTP with sprop-parameter-sets" do
expected =
"fmtp:96 profile-level-id=420029;packetization-mode=1;sprop-parameter-sets=Z0IAKeKQFAe2AtwEBAaQeJEV,aM48gA=="

fmtp = %FMTP{
pt: 96,
packetization_mode: 1,
profile_level_id: 0x420029,
sprop_parameter_sets: %{
sps: <<103, 66, 0, 41, 226, 144, 20, 7, 182, 2, 220, 4, 4, 6, 144, 120, 145, 21>>,
pps: <<104, 206, 60, 128>>
}
}

assert "#{fmtp}" == expected
end
end
end

0 comments on commit 900ee4c

Please sign in to comment.