Skip to content

Commit eff2abc

Browse files
committed
Specify variant selection policy
1 parent 572ac38 commit eff2abc

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed

lib/membrane_http_adaptive_stream/hls_source.ex

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,21 @@ defmodule Membrane.HLS.Source do
2424
flow_control: :manual,
2525
demand_unit: :buffers
2626

27+
@type variant_selection_policy() ::
28+
:lowest_resolution
29+
| :highest_resolution
30+
| :lowest_bandwidth
31+
| :highest_bandwidth
32+
| (variants_map :: %{optional(integer()) => ExHLS.Client.variant_description()} ->
33+
variant_id :: integer())
34+
2735
def_options url: [spec: String.t()],
2836
buffer_size: [spec: pos_integer(), default: 0],
29-
container: [spec: :mpeg_ts | :fmp4, default: :mpeg_ts]
37+
container: [spec: :mpeg_ts | :fmp4, default: :mpeg_ts],
38+
variant_selection_policy: [
39+
spec: variant_selection_policy(),
40+
default: :highest_resolution
41+
]
3042

3143
@impl true
3244
def handle_init(_ctx, opts) do
@@ -49,7 +61,9 @@ defmodule Membrane.HLS.Source do
4961
:fmp4 -> ExHLS.DemuxingEngine.CMAF
5062
end
5163

52-
{:ok, clinet_genserver} = ClientGenServer.start_link(state.url, demuxing_engine)
64+
{:ok, clinet_genserver} =
65+
ClientGenServer.start_link(state.url, demuxing_engine, state.variant_selection_policy)
66+
5367
{[], %{state | client_genserver: clinet_genserver}}
5468
end
5569

lib/membrane_http_adaptive_stream/hls_source/client_genserver.ex

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,18 @@ defmodule Membrane.HLS.Source.ClientGenServer do
66
use GenServer
77
alias ExHLS.Client
88

9-
@spec start_link(String.t(), ExHLS.DemuxingEngine.CMAF | ExHLS.DemuxingEngine.MPEGTS) ::
9+
@spec start_link(
10+
String.t(),
11+
ExHLS.DemuxingEngine.CMAF | ExHLS.DemuxingEngine.MPEGTS,
12+
Membrane.HLS.Source.variant_selection_policy()
13+
) ::
1014
GenServer.on_start()
11-
def start_link(url, demuxing_engine) do
12-
GenServer.start_link(__MODULE__, url: url, demuxing_engine: demuxing_engine)
15+
def start_link(url, demuxing_engine, variant_selection_policy) do
16+
GenServer.start_link(__MODULE__,
17+
url: url,
18+
demuxing_engine: demuxing_engine,
19+
variant_selection_policy: variant_selection_policy
20+
)
1321
end
1422

1523
@spec request_audio(pid()) :: :ok
@@ -28,11 +36,44 @@ defmodule Membrane.HLS.Source.ClientGenServer do
2836
end
2937

3038
@impl true
31-
def init(url: url, demuxing_engine: demuxing_engine) do
32-
client = Client.new(url, demuxing_engine)
33-
variant_id = Client.get_variants(client) |> Enum.at(0) |> elem(0)
34-
client = Client.choose_variant(client, variant_id)
35-
{:ok, %{client: client}}
39+
def init(
40+
url: url,
41+
demuxing_engine: demuxing_engine,
42+
variant_selection_policy: variant_selection_policy
43+
) do
44+
state = %{
45+
client: Client.new(url, demuxing_engine),
46+
variant_selection_policy: variant_selection_policy
47+
}
48+
49+
{:ok, state |> choose_variant()}
50+
end
51+
52+
defp choose_variant(state) do
53+
variants = Client.get_variants(state.client)
54+
get_resolution = fn {_id, %{resolution: {width, height}}} -> width * height end
55+
get_bandwidth = fn {_id, %{bandwidth: bandwidth}} -> bandwidth end
56+
57+
chosen_variant_id =
58+
case state.variant_selection_policy do
59+
:lowest_resolution ->
60+
variants |> Enum.min_by(get_resolution) |> elem(0)
61+
62+
:highest_resolution ->
63+
variants |> Enum.max_by(get_resolution) |> elem(0)
64+
65+
:lowest_bandwidth ->
66+
variants |> Enum.min_by(get_bandwidth) |> elem(0)
67+
68+
:highest_bandwidth ->
69+
variants |> Enum.max_by(get_bandwidth) |> elem(0)
70+
71+
custom_policy when is_function(custom_policy, 1) ->
72+
variants |> custom_policy.()
73+
end
74+
75+
client = state.client |> Client.choose_variant(chosen_variant_id)
76+
%{state | client: client}
3677
end
3778

3879
@impl true

0 commit comments

Comments
 (0)