-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvideo.ex
130 lines (111 loc) · 3.9 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
120
121
122
123
124
125
126
127
128
129
130
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(),
boolean()
) :: ChildrenSpec.builder()
def plug_video_transcoding(builder, input_format, output_format, enforce_transcoding?)
when is_video_format(input_format) and is_video_format(output_format) do
do_plug_video_transcoding(builder, input_format, output_format, enforce_transcoding?)
end
defp do_plug_video_transcoding(
builder,
%h26x{},
%h26x{} = output_format,
false = _enforce_transcoding?
)
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{},
false = _enforce_transcoding?
) 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, _enforce_transcoding?) 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