-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add `simulcast` and `rid` attributes * Add tests * Bump version * Apply requested changes
- Loading branch information
Showing
8 changed files
with
265 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
defmodule ExSDP.Attribute.RID do | ||
@moduledoc """ | ||
This module represents rid (RFC 8851). | ||
""" | ||
|
||
@enforce_keys [:id, :direction] | ||
defstruct @enforce_keys ++ [pt: nil, restrictions: []] | ||
|
||
@type t :: %__MODULE__{ | ||
id: binary(), | ||
direction: :send | :recv, | ||
pt: [non_neg_integer()] | nil, | ||
restrictions: {String.t(), String.t()} | ||
} | ||
|
||
@typedoc """ | ||
Key that can be used for searching this attribute using `ExSDP.Media.get_attribute/2`. | ||
""" | ||
@type attr_key :: :rid | ||
|
||
@spec parse(binary()) :: {:ok, t()} | {:error, :invalid_rid} | ||
def parse(rid) do | ||
case String.split(rid, " ") do | ||
[id, dir] when dir in ["send", "recv"] -> {:ok, id, dir, ""} | ||
[id, dir, rests] when dir in ["send", "recv"] -> {:ok, id, dir, rests} | ||
_other -> {:error, :invalid_rid} | ||
end | ||
|> case do | ||
{:ok, id, dir, rests} -> | ||
{pt, rests} = parse_restrictions(rests) | ||
dir = String.to_atom(dir) | ||
{:ok, %__MODULE__{id: id, direction: dir, pt: pt, restrictions: rests}} | ||
|
||
{:error, _res} = err -> | ||
err | ||
end | ||
end | ||
|
||
defp parse_restrictions(rests) do | ||
case String.split(rests, ";") do | ||
["pt=" <> pts | rests] -> | ||
pts = | ||
pts | ||
|> String.split(",") | ||
|> Enum.map(&Integer.parse(&1, 10)) | ||
|> Enum.flat_map(fn | ||
{int, _} -> [int] | ||
:error -> [] | ||
end) | ||
|
||
{pts, do_parse_restrictions(rests)} | ||
|
||
rests -> | ||
{nil, do_parse_restrictions(rests)} | ||
end | ||
end | ||
|
||
defp do_parse_restrictions(rests) do | ||
rests | ||
|> Enum.flat_map(fn rest -> | ||
case String.split(rest, "=", parts: 2) do | ||
[restriction, value] -> [{restriction, value}] | ||
_other -> [] | ||
end | ||
end) | ||
end | ||
end | ||
|
||
defimpl String.Chars, for: ExSDP.Attribute.RID do | ||
alias ExSDP.Attribute.RID | ||
|
||
@impl true | ||
def to_string(rid) do | ||
%RID{id: id, direction: direction, pt: pt, restrictions: rests} = rid | ||
direction = Atom.to_string(direction) | ||
|
||
pts = | ||
case pt do | ||
nil -> [] | ||
pts -> ["pt=#{Enum.join(pts, ",")}"] | ||
end | ||
|
||
rests = Enum.map(rests, fn {rest, value} -> "#{rest}=#{value}" end) | ||
|
||
pt_rests = | ||
(pts ++ rests) | ||
|> Enum.join(";") | ||
|
||
all = | ||
[id, direction, pt_rests] | ||
|> Enum.reject(&(&1 == "")) | ||
|> Enum.join(" ") | ||
|
||
"rid:#{all}" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
defmodule ExSDP.Attribute.Simulcast do | ||
@moduledoc """ | ||
This module represents simulcast (RFC 8853). | ||
""" | ||
|
||
defstruct send: [], recv: [] | ||
|
||
@type rid() :: String.t() | ||
@type t :: %__MODULE__{ | ||
send: [rid() | [rid()]], | ||
recv: [rid() | [rid()]] | ||
} | ||
|
||
@typedoc """ | ||
Key that can be used for searching this attribute using `ExSDP.Media.get_attribute/2`. | ||
""" | ||
@type attr_key :: :simulcast | ||
|
||
@spec parse(binary()) :: {:ok, t()} | {:error, :invalid_simulcast} | ||
def parse(simulcast) do | ||
case String.split(simulcast, " ") do | ||
["send", send] -> {:ok, "", send} | ||
["recv", recv] -> {:ok, recv, ""} | ||
["recv", recv, "send", send] -> {:ok, recv, send} | ||
["send", send, "recv", recv] -> {:ok, recv, send} | ||
_other -> {:error, :invalid_simulcast} | ||
end | ||
|> case do | ||
{:ok, recv, send} -> | ||
send = parse_streams(send) | ||
recv = parse_streams(recv) | ||
{:ok, %__MODULE__{send: send, recv: recv}} | ||
|
||
{:error, _res} = err -> | ||
err | ||
end | ||
end | ||
|
||
defp parse_streams(""), do: [] | ||
|
||
defp parse_streams(streams) do | ||
streams | ||
|> String.split(";") | ||
|> Enum.map(&String.split(&1, ",")) | ||
|> Enum.map(fn | ||
[rid] -> rid | ||
rids -> rids | ||
end) | ||
end | ||
end | ||
|
||
defimpl String.Chars, for: ExSDP.Attribute.Simulcast do | ||
alias ExSDP.Attribute.Simulcast | ||
|
||
@impl true | ||
def to_string(simulcast) do | ||
%Simulcast{send: send, recv: recv} = simulcast | ||
send = encode_streams(send) | ||
send = if(send == "", do: [], else: ["send", send]) | ||
recv = encode_streams(recv) | ||
recv = if(recv == "", do: [], else: ["recv", recv]) | ||
send_recv = Enum.join(send ++ recv, " ") | ||
|
||
"simulcast:#{send_recv}" | ||
end | ||
|
||
defp encode_streams(streams) do | ||
Enum.map_join(streams, ";", fn | ||
rids when is_list(rids) -> Enum.join(rids, ",") | ||
rid -> rid | ||
end) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
defmodule ExSDP.Attribute.RIDTest do | ||
use ExUnit.Case, async: true | ||
|
||
alias ExSDP.Attribute.RID | ||
|
||
test "parse/1" do | ||
assert {:ok, rid} = RID.parse("l recv") | ||
assert %RID{id: "l", direction: :recv, pt: nil, restrictions: []} == rid | ||
|
||
assert {:ok, rid} = RID.parse("h send pt=4,5") | ||
assert %RID{id: "h", direction: :send, pt: [4, 5], restrictions: []} == rid | ||
|
||
assert {:ok, rid} = RID.parse("m send max-width=1280;max-fps=30") | ||
|
||
assert %RID{ | ||
id: "m", | ||
direction: :send, | ||
pt: nil, | ||
restrictions: [{"max-width", "1280"}, {"max-fps", "30"}] | ||
} == rid | ||
|
||
assert {:ok, rid} = RID.parse("m recv pt=111;max-fps=30") | ||
assert %RID{id: "m", direction: :recv, pt: [111], restrictions: [{"max-fps", "30"}]} == rid | ||
end | ||
|
||
test "to_string/1" do | ||
rid = %RID{id: "l", direction: :recv, pt: nil, restrictions: []} | ||
assert to_string(rid) == "rid:l recv" | ||
|
||
rid = %RID{id: "h", direction: :send, pt: [4, 5], restrictions: []} | ||
assert to_string(rid) == "rid:h send pt=4,5" | ||
|
||
rid = %RID{ | ||
id: "m", | ||
direction: :send, | ||
pt: nil, | ||
restrictions: [{"max-width", "1280"}, {"max-fps", "30"}] | ||
} | ||
|
||
assert to_string(rid) == "rid:m send max-width=1280;max-fps=30" | ||
|
||
rid = %RID{id: "m", direction: :recv, pt: [111], restrictions: [{"max-fps", "30"}]} | ||
assert to_string(rid) == "rid:m recv pt=111;max-fps=30" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
defmodule ExSDP.Attribute.SimulcastTest do | ||
use ExUnit.Case, async: true | ||
|
||
alias ExSDP.Attribute.Simulcast | ||
|
||
test "parse/1" do | ||
assert {:ok, simulcast} = Simulcast.parse("recv l;h;m send l;h") | ||
assert %Simulcast{recv: ["l", "h", "m"], send: ["l", "h"]} == simulcast | ||
|
||
assert {:ok, simulcast} = Simulcast.parse("send l;h;m") | ||
assert %Simulcast{recv: [], send: ["l", "h", "m"]} == simulcast | ||
|
||
assert {:ok, simulcast} = Simulcast.parse("send l;m;3 recv 1,2;5") | ||
assert %Simulcast{recv: [["1", "2"], "5"], send: ["l", "m", "3"]} == simulcast | ||
|
||
assert {:error, :invalid_simulcast} = Simulcast.parse("send l;h,5, rec") | ||
end | ||
|
||
test "to_string/1" do | ||
simulcast = %Simulcast{recv: ["l", "h", "m"], send: ["l", "h"]} | ||
assert to_string(simulcast) == "simulcast:send l;h recv l;h;m" | ||
|
||
simulcast = %Simulcast{recv: [], send: ["l", "h", "m"]} | ||
assert to_string(simulcast) == "simulcast:send l;h;m" | ||
|
||
simulcast = %Simulcast{recv: [["1", "2"], "5"], send: ["l", "m", "3"]} | ||
assert to_string(simulcast) == "simulcast:send l;m;3 recv 1,2;5" | ||
end | ||
end |