Skip to content

Commit

Permalink
Specify pad codec
Browse files Browse the repository at this point in the history
  • Loading branch information
FelonEkonom committed Jun 21, 2024
1 parent 72d38a0 commit f5ca181
Showing 1 changed file with 109 additions and 4 deletions.
113 changes: 109 additions & 4 deletions lib/membrane_mp4/demuxer/isom.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,19 @@ defmodule Membrane.MP4.Demuxer.ISOM do
%Membrane.Opus{self_delimiting?: false}
),
availability: :on_request,
flow_control: :auto
options: [
codec: [
spec: Membrane.H264 | Membrane.H265 | Membrane.Opus | Membrane.AAC | :all,
default: :all,
description: """
Specifies, what kind of codec can be handled by a pad.
Pad with `:codec` option set to `:all` can handle all codecs.
Defaults to `:all`
"""
]
]

def_options optimize_for_non_fast_start?: [
default: false,
Expand Down Expand Up @@ -82,7 +94,9 @@ defmodule Membrane.MP4.Demuxer.ISOM do
boxes_size: 0,
mdat_beginning: nil,
mdat_size: nil,
mdat_header_size: nil
mdat_header_size: nil,
track_to_pad_id: %{},
tracks_notifications: %{}
}

{[], state}
Expand Down Expand Up @@ -365,7 +379,9 @@ defmodule Membrane.MP4.Demuxer.ISOM do
{[], store_samples(state, samples)}
end

state = match_tracks_with_pads(ctx, state)
notifications = get_track_notifications(state)

stream_format = if all_pads_connected?, do: get_stream_format(state), else: []

state =
Expand Down Expand Up @@ -398,12 +414,80 @@ defmodule Membrane.MP4.Demuxer.ISOM do
end
end

defp match_tracks_with_pads(ctx, state) do
codec_to_tracks =
state.samples_info.sample_tables
|> Enum.group_by(
fn {_track_id, table} -> table.sample_description.__struct__ end,
fn {track_id, _table} -> track_id end
)

output_pads_with_specyfied_codec =
ctx.pads
|> Enum.flat_map(fn
{:input, _pad_data} -> []
{_output, %{options: %{codec: :all}}} -> []
{_output, pad_data} -> [pad_data]
end)

{matching_track_to_pad_id, codec_to_tracks_left} =
output_pads_with_specyfied_codec
|> Enum.map_reduce(codec_to_tracks, fn pad_data, codec_to_tracks ->
pad_codec = pad_data.options.codec

case codec_to_tracks[pad_codec] do
[matched_track | tracks] ->
codec_to_tracks = Map.put(codec_to_tracks, pad_codec, tracks)
Pad.ref(:output, pad_id) = pad_data.ref
{{matched_track, pad_id}, codec_to_tracks}

_else ->
raise "There is no track with codec #{inspect(pad_codec)} for pad #{inspect(pad_data.ref)}"
end
end)

pads_without_specyfied_codec =
ctx.pads
|> Enum.flat_map(fn
{Pad.ref(:output, id), %{options: %{codec: :all}}} -> [id]
_other -> []
end)

left_tracks_matching =
Map.values(codec_to_tracks_left)
|> List.flatten()
|> zip_all(pads_without_specyfied_codec)
|> Enum.map(fn
{track, nil} -> {track, track}
{track, pad} -> {track, pad}
end)

matching_track_to_pad_id =
left_tracks_matching
|> Enum.concat(matching_track_to_pad_id)
|> Map.new()

%{state | track_to_pad_id: matching_track_to_pad_id}
end

defp zip_all(enum1, enum2) do
len1 = length(enum1)
len2 = length(enum2)

tail = Stream.repeatedly(fn -> nil end) |> Enum.take(abs(len1 - len2))

enum1 = if len1 < len2, do: enum1 ++ tail, else: enum1
enum2 = if len1 > len2, do: enum2 ++ tail, else: enum2

Enum.zip(enum1, enum2)
end

defp get_track_notifications(state) do
new_tracks =
state.samples_info.sample_tables
|> Enum.map(fn {track_id, table} ->
content = table.sample_description
{track_id, content}
pad_id = state.track_to_pad_id[track_id]
{pad_id, table.sample_description}
end)

[{:notify_parent, {:new_tracks, new_tracks}}]
Expand All @@ -425,11 +509,25 @@ defmodule Membrane.MP4.Demuxer.ISOM do
raise "All tracks have corresponding pad already connected"
end

# def handle_pad_added(Pad.ref(:output, pad_id), %{playback: :stopped} = ctx, state) do
# # git
# end

def handle_pad_added(Pad.ref(:output, _track_id), ctx, state) do
# case

# do

# jesli zostal zalączany track

all_pads_connected? = all_pads_connected?(ctx, state)

{actions, state} =
if all_pads_connected? do
if ctx.playback != :playing do
raise "tak nie moze byc :("
end

{buffer_actions, state} = flush_samples(state)
maybe_stream_format = if state.samples_info != nil, do: get_stream_format(state), else: []
maybe_eos = if state.end_of_stream?, do: get_end_of_stream_actions(ctx), else: []
Expand Down Expand Up @@ -458,6 +556,13 @@ defmodule Membrane.MP4.Demuxer.ISOM do
defp all_pads_connected?(ctx, state) do
tracks = 1..state.samples_info.tracks_number

# tracks_grouped_by_codec =
# state.samples_info.sample_tables
# |> Enum.group_by(
# fn {_track_id, table} -> table.sample_description.__struct__ end,
# fn {track_id, _table} -> track_id end
# )

pads =
ctx.pads
|> Enum.flat_map(fn
Expand Down

0 comments on commit f5ca181

Please sign in to comment.