Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for AV1 FMTP attributes #44

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions lib/ex_sdp/attribute/fmtp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule ExSDP.Attribute.FMTP do
* H264 (not all, RFC 6184),
* H265 (not all, RFC 7798)
* VP8, VP9, OPUS (RFC 7587)
* AV1 (no RFC, https://aomediacodec.github.io/av1-rtp-spec/)
* RTX (RFC 4588)
* FLEXFEC (RFC 8627)
* Telephone Events (RFC 4733)
Expand Down Expand Up @@ -53,6 +54,10 @@ defmodule ExSDP.Attribute.FMTP do
:usedtx,
# VP8/9
:max_fr,
# AV1
:profile,
:level_idx,
:tier,
# RTX
:apt,
:rtx_time,
Expand Down Expand Up @@ -97,6 +102,10 @@ defmodule ExSDP.Attribute.FMTP do
usedtx: boolean() | nil,
# VP8/9
max_fr: non_neg_integer() | nil,
# AV1
profile: non_neg_integer() | nil,
level_idx: non_neg_integer() | nil,
tier: non_neg_integer() | nil,
# RTX
apt: RTPMapping.payload_type_t() | nil,
rtx_time: non_neg_integer() | nil,
Expand Down Expand Up @@ -289,6 +298,21 @@ defmodule ExSDP.Attribute.FMTP do
do: {rest, %{fmtp | max_fr: value}}
end

defp parse_param(["profile=" <> max_fr | rest], fmtp) do
with {:ok, value} <- Utils.parse_numeric_string(max_fr),
do: {rest, %{fmtp | profile: value}}
end

defp parse_param(["level-idx=" <> max_fr | rest], fmtp) do
with {:ok, value} <- Utils.parse_numeric_string(max_fr),
do: {rest, %{fmtp | level_idx: value}}
end

defp parse_param(["tier=" <> max_fr | rest], fmtp) do
with {:ok, value} <- Utils.parse_numeric_string(max_fr),
do: {rest, %{fmtp | tier: value}}
end

defp parse_param(["apt=" <> value | rest], fmtp) do
with {:ok, value} <- Utils.parse_payload_type(value), do: {rest, %{fmtp | apt: value}}
end
Expand Down Expand Up @@ -397,6 +421,10 @@ defimpl String.Chars, for: ExSDP.Attribute.FMTP do
# RTX
Serializer.maybe_serialize("apt", fmtp.apt),
Serializer.maybe_serialize("rtx-time", fmtp.rtx_time),
# AV1
Serializer.maybe_serialize("profile", fmtp.profile),
Serializer.maybe_serialize("level-idx", fmtp.level_idx),
Serializer.maybe_serialize("tier", fmtp.tier),
# FLEXFEC
Serializer.maybe_serialize("repair-window", fmtp.repair_window),
# Telephone Events
Expand Down
13 changes: 13 additions & 0 deletions test/ex_sdp/attribute/fmtp_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,19 @@ defmodule ExSDP.Attribute.FMTPTest do
assert {:ok, expected} == FMTP.parse(fmtp)
end

test "parses proper fmtp with av1 parameters" do
fmtp = "98 profile=2; level-idx=8; tier=1"

expected = %FMTP{
pt: 98,
profile: 2,
level_idx: 8,
tier: 1
}

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
17 changes: 16 additions & 1 deletion test/webrtc_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ defmodule ExSDP.WebRTCTest do
a=fmtp:63 111/111
a=ssrc:10136459 cname:fsp95kJbiDm+35qA
a=ssrc:10136459 msid:040ad92b-583f-44d2-93e8-de4d40ac49ec 730bdafa-23f3-4111-85b4-757a666d462c
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101
c=IN IP4 0.0.0.0
a=ice-ufrag:zPE+
a=ice-pwd:5uuTJKfWTxRYyERtPlvUeKsU
Expand Down Expand Up @@ -198,6 +198,19 @@ defmodule ExSDP.WebRTCTest do
a=fmtp:98 profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 AV1/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtpmap:101 AV1/90000
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=fmtp:101 profile=1
a=ssrc-group:FID 1984225447 2555509203
a=ssrc:1984225447 cname:fsp95kJbiDm+35qA
a=ssrc:1984225447 msid:b5f40727-fa04-44db-9f4c-35c5fe8f2c3a a68d0021-2492-4f05-a211-e6b9b19c57ff
Expand Down Expand Up @@ -226,6 +239,8 @@ defmodule ExSDP.WebRTCTest do
assert %ExSDP.Attribute.RTCPFeedback{pt: 98, feedback_type: :pli} in video.attributes
assert %ExSDP.Attribute.FMTP{pt: 99, apt: 98} in video.attributes

assert %ExSDP.Attribute.FMTP{pt: 101, profile: 1} in video.attributes

assert video.attributes |> Enum.at(-5) == %ExSDP.Attribute.SSRCGroup{
semantics: "FID",
ssrcs: [1_984_225_447, 2_555_509_203]
Expand Down
Loading