/
gstreamer_utils.ml
112 lines (95 loc) · 3.73 KB
/
gstreamer_utils.ml
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
open Dtools
module Img = Image.RGBA32
let conf_gstreamer =
Conf.void ~p:(Configure.conf#plug "gstreamer")
"Media decoding/endcoding through gstreamer."
let conf_debug =
Conf.int ~p:(conf_gstreamer#plug "debug_level") ~d:0
"Debug level (bewteen 0 and 5)."
let conf_max_buffers =
Conf.int ~p:(conf_gstreamer#plug "max_buffers") ~d:10
"Maximal number of buffers."
let max_buffers () = conf_max_buffers#get
let conf_add_borders =
Conf.bool ~p:(conf_gstreamer#plug "add_borders") ~d:true
"Add borders in order to keep video aspect ratio."
let add_borders () = conf_add_borders#get
let init =
let inited = ref false in
fun () ->
let argv =
[|
"Liquidsoap";
"--gst-debug-spew";
Printf.sprintf "--gst-debug-level=%d" conf_debug#get
|]
in
if not !inited then
(
inited := true;
Gstreamer.init ~argv ()
)
module Pipeline = struct
let convert_audio () =
"audioconvert ! audioresample"
let decode_audio () =
Printf.sprintf "decodebin ! %s" (convert_audio ())
let convert_video () =
let add_borders = add_borders () in
Printf.sprintf "videoconvert ! videoscale add-borders=%B ! videorate"
add_borders
let audio_format channels =
let rate = Lazy.force Frame.audio_rate in
Printf.sprintf "audio/x-raw,format=S16LE,layout=interleaved,channels=%d,rate=%d"
channels rate
let audio_src ~channels ?(block=true) ?(format=Gstreamer.Format.Time) name =
Printf.sprintf "appsrc name=\"%s\" block=%B caps=\"%s\" format=%s"
name block (audio_format channels) (Gstreamer.Format.to_string format)
let audio_sink ?(drop=false) ?(sync=false) ?max_buffers ~channels name =
let max_buffers =
match max_buffers with
| None -> conf_max_buffers#get
| Some m -> m
in
Printf.sprintf "appsink max-buffers=%d drop=%B sync=%B name=\"%s\" caps=\"%s\""
max_buffers drop sync name
(audio_format channels)
let video_format () =
let width = Lazy.force Frame.video_width in
let height = Lazy.force Frame.video_height in
let fps = Lazy.force Frame.video_rate in
Printf.sprintf
"video/x-raw,format=RGBA,width=%d,height=%d,framerate=%d/1,pixel-aspect-ratio=1/1"
width height fps
let video_src ?(block=true) ?(format=Gstreamer.Format.Time) name =
let width = Lazy.force Frame.video_width in
let height = Lazy.force Frame.video_height in
let blocksize = width * height * 4 in
Printf.sprintf "appsrc name=\"%s\" block=%B caps=\"%s\" format=%s blocksize=%d"
name block (video_format ()) (Gstreamer.Format.to_string format) blocksize
let video_sink ?(drop=false) ?(sync=false) ?max_buffers name =
let max_buffers =
match max_buffers with
| None -> conf_max_buffers#get
| Some m -> m
in
Printf.sprintf
"appsink name=\"%s\" drop=%B sync=%B max-buffers=%d caps=\"%s\""
name drop sync max_buffers
(video_format ())
let decode_video () =
Printf.sprintf "decodebin ! %s" (convert_video ())
end
let render_image pipeline =
let width = Lazy.force Frame.video_width in
let height = Lazy.force Frame.video_height in
let pipeline = Printf.sprintf "%s ! %s ! %s" pipeline (Pipeline.convert_video ()) (Pipeline.video_sink ~drop:false ~max_buffers:1 "sink") in
(* Printf.printf "render_image pipeline: %s\n%!" pipeline; *)
let bin = Gstreamer.Pipeline.parse_launch pipeline in
let sink = Gstreamer.App_sink.of_element (Gstreamer.Bin.get_by_name bin "sink") in
ignore (Gstreamer.Element.set_state bin Gstreamer.Element.State_playing);
ignore (Gstreamer.Element.get_state bin);
let buf = Gstreamer.App_sink.pull_buffer sink in
let img = Img.make width height buf in
ignore (Gstreamer.Element.set_state bin Gstreamer.Element.State_null);
img