Packages
membrane_rtc_engine
0.14.2
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.1
0.17.0
0.16.0
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.0
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.0
0.1.0
0.1.0-alpha.2
0.1.0-alpha.1
0.1.0-alpha
Membrane RTC Engine and its client library
Current section
Files
Jump to
Current section
Files
lib/membrane_rtc_engine/endpoints/webrtc/vp8_munger.ex
defmodule Membrane.RTC.Engine.Endpoint.WebRTC.VP8Munger do
@moduledoc false
# Module responsible for rewriting VP8 RTP payload fields
# to provide transparent switch between simulcast encodings.
import Bitwise
alias Membrane.Buffer
alias Membrane.RTP.VP8
@type t() :: %__MODULE__{
pic_id_used: boolean(),
last_pic_id: integer(),
pic_id_offset: integer(),
tl0picidx_used: boolean(),
last_tl0picidx: integer(),
tl0picidx_offset: integer(),
keyidx_used: boolean(),
last_keyidx: integer(),
keyidx_offset: integer()
}
defstruct pic_id_used: false,
last_pic_id: 0,
pic_id_offset: 0,
tl0picidx_used: false,
last_tl0picidx: 0,
tl0picidx_offset: 0,
keyidx_used: false,
last_keyidx: 0,
keyidx_offset: 0
@spec new() :: t()
def new() do
%__MODULE__{}
end
@spec init(t(), Membrane.Buffer.t()) :: t()
def init(vp8_munger, buffer) do
{:ok, {payload_descriptor, _payload}} =
VP8.PayloadDescriptor.parse_payload_descriptor(buffer.payload)
%VP8.PayloadDescriptor{
i: i,
keyidx: keyidx,
l: l,
picture_id: pic_id,
k: k,
tl0picidx: tl0picidx
} = payload_descriptor
pic_id_used = i == 1
tl0picidx_used = l == 1
keyidx_used = k == 1
last_pic_id = if pic_id_used, do: pic_id, else: 0
last_tl0picidx = if tl0picidx_used, do: tl0picidx, else: 0
last_keyidx = if keyidx_used, do: keyidx, else: 0
%__MODULE__{
vp8_munger
| pic_id_used: pic_id_used,
last_pic_id: last_pic_id,
tl0picidx_used: tl0picidx_used,
last_tl0picidx: last_tl0picidx,
keyidx_used: keyidx_used,
last_keyidx: last_keyidx
}
end
@spec update(t(), Membrane.Buffer.t()) :: t()
def update(vp8_munger, buffer) do
{:ok, {payload_descriptor, _payload}} =
VP8.PayloadDescriptor.parse_payload_descriptor(buffer.payload)
%VP8.PayloadDescriptor{
keyidx: keyidx,
picture_id: pic_id,
tl0picidx: tl0picidx
} = payload_descriptor
pic_id_offset = if vp8_munger.pic_id_used, do: pic_id - vp8_munger.last_pic_id - 1, else: 0
tl0picidx_offset =
if vp8_munger.tl0picidx_used, do: tl0picidx - vp8_munger.last_tl0picidx - 1, else: 0
keyidx_offset = if vp8_munger.keyidx_used, do: keyidx - vp8_munger.last_keyidx - 1, else: 0
%__MODULE__{
vp8_munger
| pic_id_offset: pic_id_offset,
tl0picidx_offset: tl0picidx_offset,
keyidx_offset: keyidx_offset
}
end
@spec munge(t(), Membrane.Buffer.t()) :: {t(), Membrane.Buffer.t()}
def munge(vp8_munger, %Membrane.Buffer{payload: <<>>} = buffer), do: {vp8_munger, buffer}
def munge(vp8_munger, buffer) do
{:ok, {payload_descriptor, vp8_payload}} =
VP8.PayloadDescriptor.parse_payload_descriptor(buffer.payload)
%VP8.PayloadDescriptor{
keyidx: keyidx,
picture_id: pic_id,
tl0picidx: tl0picidx
} = payload_descriptor
munged_pic_id = rem(pic_id + (1 <<< 15) - vp8_munger.pic_id_offset, 1 <<< 15)
munged_tl0picidx = rem(tl0picidx + (1 <<< 8) - vp8_munger.tl0picidx_offset, 1 <<< 8)
munged_keyidx = rem(keyidx + (1 <<< 5) - vp8_munger.keyidx_offset, 1 <<< 5)
buffer =
%VP8.PayloadDescriptor{
payload_descriptor
| keyidx: munged_keyidx,
picture_id: munged_pic_id,
tl0picidx: munged_tl0picidx
}
|> VP8.PayloadDescriptor.serialize()
|> then(fn munged_payload_descriptor ->
%Buffer{buffer | payload: munged_payload_descriptor <> vp8_payload}
end)
vp8_munger = %__MODULE__{
vp8_munger
| last_pic_id: munged_pic_id,
last_tl0picidx: munged_tl0picidx,
last_keyidx: munged_keyidx
}
{vp8_munger, buffer}
end
end