-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvideo.ex
119 lines (100 loc) · 3.67 KB
/
video.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
defmodule Membrane.Transcoder.Video do
@moduledoc false
import Membrane.ChildrenSpec
require Membrane.Logger
alias Membrane.{ChildrenSpec, H264, H265, RawVideo, RemoteStream, VP8}
@type video_stream_format :: VP8.t() | H264.t() | H265.t() | RawVideo.t()
defguard is_video_format(format)
when is_struct(format) and
(format.__struct__ in [VP8, H264, H265, RawVideo] or
(format.__struct__ == RemoteStream and format.content_format == VP8 and
format.type == :packetized))
@spec plug_video_transcoding(
ChildrenSpec.builder(),
video_stream_format(),
video_stream_format()
) :: ChildrenSpec.builder()
def plug_video_transcoding(builder, input_format, output_format)
when is_video_format(input_format) and is_video_format(output_format) do
do_plug_video_transcoding(builder, input_format, output_format)
end
defp do_plug_video_transcoding(builder, %h26x{}, %h26x{} = output_format)
when h26x in [H264, H265] do
parser =
h26x
|> Module.concat(Parser)
|> struct!(
output_stream_structure: stream_structure_type(output_format),
output_alignment: output_format.alignment
)
builder |> child(:h264_parser, parser)
end
defp do_plug_video_transcoding(builder, %format_module{}, %format_module{}) do
Membrane.Logger.debug("""
This bin will only forward buffers, as the input stream format is the same type as the output stream format.
""")
builder
end
defp do_plug_video_transcoding(builder, input_format, output_format) do
builder
|> maybe_plug_parser_and_decoder(input_format)
|> maybe_plug_encoder_and_parser(output_format)
end
defp maybe_plug_parser_and_decoder(builder, %H264{}) do
builder
|> child(:h264_input_parser, %H264.Parser{
output_stream_structure: :annexb,
output_alignment: :au
})
|> child(:h264_decoder, %H264.FFmpeg.Decoder{})
end
defp maybe_plug_parser_and_decoder(builder, %H265{}) do
builder
|> child(:h265_input_parser, %H265.Parser{
output_stream_structure: :annexb,
output_alignment: :au
})
|> child(:h265_decoder, %H265.FFmpeg.Decoder{})
end
defp maybe_plug_parser_and_decoder(builder, %VP8{}) do
builder |> child(:vp8_decoder, %VP8.Decoder{})
end
defp maybe_plug_parser_and_decoder(builder, %RemoteStream{
content_format: VP8,
type: :packetized
}) do
builder |> child(:vp8_decoder, %VP8.Decoder{})
end
defp maybe_plug_parser_and_decoder(builder, %RawVideo{}) do
builder
end
defp maybe_plug_encoder_and_parser(builder, %H264{} = h264) do
builder
|> child(:h264_encoder, %H264.FFmpeg.Encoder{preset: :ultrafast})
|> child(:h264_output_parser, %H264.Parser{
output_stream_structure: stream_structure_type(h264),
output_alignment: h264.alignment
})
end
defp maybe_plug_encoder_and_parser(builder, %H265{} = h265) do
builder
|> child(:h265_encoder, %H265.FFmpeg.Encoder{preset: :ultrafast})
|> child(:h265_output_parser, %H265.Parser{
output_stream_structure: stream_structure_type(h265),
output_alignment: h265.alignment
})
end
defp maybe_plug_encoder_and_parser(builder, %VP8{}) do
builder |> child(:vp8_encoder, %VP8.Encoder{})
end
defp maybe_plug_encoder_and_parser(builder, %RawVideo{}) do
builder
end
defp stream_structure_type(%h26x{stream_structure: stream_structure})
when h26x in [H264, H265] do
case stream_structure do
type when type in [:annexb, :avc1, :avc3, :hvc1, :hev1] -> type
{type, _dcr} when type in [:avc1, :avc3, :hvc1, :hev1] -> type
end
end
end