Update example
This commit is contained in:
parent
d8e9295b91
commit
fc9707fe66
2 changed files with 51 additions and 335 deletions
296
pipeline.dot
296
pipeline.dot
|
@ -1,296 +0,0 @@
|
||||||
digraph pipeline {
|
|
||||||
rankdir=LR;
|
|
||||||
fontname="sans";
|
|
||||||
fontsize="10";
|
|
||||||
labelloc=t;
|
|
||||||
nodesep=.1;
|
|
||||||
ranksep=.2;
|
|
||||||
label="<GstPipeline>\npipeline0\n[>]";
|
|
||||||
node [style="filled,rounded", shape=box, fontsize="9", fontname="sans", margin="0.0,0.0"];
|
|
||||||
edge [labelfontsize="6", fontsize="9", fontname="monospace"];
|
|
||||||
|
|
||||||
legend [
|
|
||||||
pos="0,0!",
|
|
||||||
margin="0.05,0.05",
|
|
||||||
style="filled",
|
|
||||||
label="Legend\lElement-States: [~] void-pending, [0] null, [-] ready, [=] paused, [>] playing\lPad-Activation: [-] none, [>] push, [<] pull\lPad-Flags: [b]locked, [f]lushing, [b]locking, [E]OS; upper-case is set\lPad-Task: [T] has started task, [t] has paused task\l",
|
|
||||||
];
|
|
||||||
subgraph cluster_capsfilter1_0x7f8f2691e5d0 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstCapsFilter\ncapsfilter1\n[>]\ncaps=video/x-h264, profile=(string)main";
|
|
||||||
subgraph cluster_capsfilter1_0x7f8f2691e5d0_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
capsfilter1_0x7f8f2691e5d0_sink_0x7f8f23076e20 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_capsfilter1_0x7f8f2691e5d0_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
capsfilter1_0x7f8f2691e5d0_src_0x7f8f23077070 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
capsfilter1_0x7f8f2691e5d0_sink_0x7f8f23076e20 -> capsfilter1_0x7f8f2691e5d0_src_0x7f8f23077070 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
capsfilter1_0x7f8f2691e5d0_src_0x7f8f23077070 -> queue0_0x7f8f24028010_sink_0x7f8f268f0d50 [label="video/x-h264\l stream-format: byte-stream\l alignment: au\l level: 3.1\l profile: main\l width: 1280\l height: 720\l pixel-aspect-ratio: 1/1\l framerate: 30/1\l interlace-mode: progressive\l colorimetry: bt709\l chroma-site: mpeg2\l multiview-mode: mono\l multiview-flags: 0:ffffffff:/right-view...\l"]
|
|
||||||
subgraph cluster_capsfilter0_0x7f8f2691e290 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstCapsFilter\ncapsfilter0\n[>]\ncaps=video/x-raw, framerate=(fraction)30/1, width=(int)1280, height=(int)720";
|
|
||||||
subgraph cluster_capsfilter0_0x7f8f2691e290_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
capsfilter0_0x7f8f2691e290_sink_0x7f8f23076980 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_capsfilter0_0x7f8f2691e290_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
capsfilter0_0x7f8f2691e290_src_0x7f8f23076bd0 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
capsfilter0_0x7f8f2691e290_sink_0x7f8f23076980 -> capsfilter0_0x7f8f2691e290_src_0x7f8f23076bd0 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
capsfilter0_0x7f8f2691e290_src_0x7f8f23076bd0 -> timeoverlay0_0x7f8f268f2a00_video_sink_0x7f8f268f0410 [label="video/x-raw\l format: I420\l width: 1280\l height: 720\l framerate: 30/1\l multiview-mode: mono\l pixel-aspect-ratio: 1/1\l interlace-mode: progressive\l"]
|
|
||||||
subgraph cluster_queue1_0x7f8f24028310 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstQueue\nqueue1\n[>]";
|
|
||||||
subgraph cluster_queue1_0x7f8f24028310_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
queue1_0x7f8f24028310_sink_0x7f8f230764e0 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_queue1_0x7f8f24028310_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
queue1_0x7f8f24028310_src_0x7f8f23076730 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb][T]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
queue1_0x7f8f24028310_sink_0x7f8f230764e0 -> queue1_0x7f8f24028310_src_0x7f8f23076730 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
queue1_0x7f8f24028310_src_0x7f8f23076730 -> mux_0x7f8f23062190_sink_66_0x7f8f26008f60 [label="audio/mpeg\l channels: 1\l rate: 44100\l mpegversion: 4\l base-profile: lc\l framed: true\l stream-format: raw\l level: 2\l profile: lc\l codec_data: 120856e500\l"]
|
|
||||||
subgraph cluster_avenc_aac0_0x7f8f268fb270 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="avenc_aac\navenc_aac0\n[>]\nbitrate=128000";
|
|
||||||
subgraph cluster_avenc_aac0_0x7f8f268fb270_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
avenc_aac0_0x7f8f268fb270_sink_0x7f8f23076040 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_avenc_aac0_0x7f8f268fb270_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
avenc_aac0_0x7f8f268fb270_src_0x7f8f23076290 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
avenc_aac0_0x7f8f268fb270_sink_0x7f8f23076040 -> avenc_aac0_0x7f8f268fb270_src_0x7f8f23076290 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
avenc_aac0_0x7f8f268fb270_src_0x7f8f23076290 -> queue1_0x7f8f24028310_sink_0x7f8f230764e0 [label="audio/mpeg\l channels: 1\l rate: 44100\l mpegversion: 4\l base-profile: lc\l framed: true\l stream-format: raw\l level: 2\l profile: lc\l codec_data: 120856e500\l"]
|
|
||||||
subgraph cluster_audioconvert0_0x7f8f230754d0 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstAudioConvert\naudioconvert0\n[>]";
|
|
||||||
subgraph cluster_audioconvert0_0x7f8f230754d0_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
audioconvert0_0x7f8f230754d0_sink_0x7f8f268f1b30 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_audioconvert0_0x7f8f230754d0_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
audioconvert0_0x7f8f230754d0_src_0x7f8f268f1d80 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
audioconvert0_0x7f8f230754d0_sink_0x7f8f268f1b30 -> audioconvert0_0x7f8f230754d0_src_0x7f8f268f1d80 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
audioconvert0_0x7f8f230754d0_src_0x7f8f268f1d80 -> avenc_aac0_0x7f8f268fb270_sink_0x7f8f23076040 [label="audio/x-raw\l rate: 44100\l channels: 1\l format: F32LE\l layout: interleaved\l"]
|
|
||||||
subgraph cluster_audiotestsrc0_0x7f8f23071ce0 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstAudioTestSrc\naudiotestsrc0\n[>]\nis-live=TRUE";
|
|
||||||
subgraph cluster_audiotestsrc0_0x7f8f23071ce0_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
audiotestsrc0_0x7f8f23071ce0_src_0x7f8f268f18e0 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb][T]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
fillcolor="#ffaaaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
audiotestsrc0_0x7f8f23071ce0_src_0x7f8f268f18e0 -> audioconvert0_0x7f8f230754d0_sink_0x7f8f268f1b30 [label="audio/x-raw\l rate: 44100\l channels: 1\l format: F32LE\l layout: interleaved\l"]
|
|
||||||
subgraph cluster_udpsink0_0x7f8f2305ba90 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstUDPSink\nudpsink0\n[>]\nlast-sample=((GstSample*) 0x7f8f2607d420)\nbytes-to-serve=50187776\nbytes-served=50187776\nused-socket=((GSocket*) 0x7f8f26016130)\nused-socket-v6=((GSocket*) 0x7f8f26016280)\nclients=\"184.73.103.62:5000\"\nhost=\"184.73.103.62\"\nport=5000";
|
|
||||||
subgraph cluster_udpsink0_0x7f8f2305ba90_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
udpsink0_0x7f8f2305ba90_sink_0x7f8f268f1690 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
fillcolor="#aaaaff";
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_rtpmp2tpay0_0x7f8f2306c0f0 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstRTPMP2TPay\nrtpmp2tpay0\n[>]\npt=33\ntimestamp=1905327734\nseqnum=3460";
|
|
||||||
subgraph cluster_rtpmp2tpay0_0x7f8f2306c0f0_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
rtpmp2tpay0_0x7f8f2306c0f0_sink_0x7f8f268f1440 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_rtpmp2tpay0_0x7f8f2306c0f0_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
rtpmp2tpay0_0x7f8f2306c0f0_src_0x7f8f268f11f0 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
rtpmp2tpay0_0x7f8f2306c0f0_sink_0x7f8f268f1440 -> rtpmp2tpay0_0x7f8f2306c0f0_src_0x7f8f268f11f0 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
rtpmp2tpay0_0x7f8f2306c0f0_src_0x7f8f268f11f0 -> udpsink0_0x7f8f2305ba90_sink_0x7f8f268f1690 [label="application/x-rtp\l media: video\l clock-rate: 90000\l encoding-name: MP2T\l payload: 33\l seqnum-offset: 31205\l timestamp-offset: 1889868735\l ssrc: 3127985935\l"]
|
|
||||||
subgraph cluster_mux_0x7f8f23062190 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstMpegTsMux\nmux\n[>]\nalignment=7\nscte-35-pid=500\nscte-35-null-interval=450000";
|
|
||||||
subgraph cluster_mux_0x7f8f23062190_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
mux_0x7f8f23062190_sink_65_0x7f8f26012960 [color=black, fillcolor="#aaaaff", label="sink_65\n[>][bfb]", height="0.2", style="filled,dashed"];
|
|
||||||
mux_0x7f8f23062190_sink_66_0x7f8f26008f60 [color=black, fillcolor="#aaaaff", label="sink_66\n[>][bfb]", height="0.2", style="filled,dashed"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_mux_0x7f8f23062190_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
mux_0x7f8f23062190_src_0x7f8f23008360 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb][T]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
mux_0x7f8f23062190_sink_65_0x7f8f26012960 -> mux_0x7f8f23062190_src_0x7f8f23008360 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
mux_0x7f8f23062190_src_0x7f8f23008360 -> rtpmp2tpay0_0x7f8f2306c0f0_sink_0x7f8f268f1440 [label="video/mpegts\l systemstream: true\l packetsize: 188\l streamheader: < (buffer)47400031a6... >\l"]
|
|
||||||
subgraph cluster_queue0_0x7f8f24028010 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstQueue\nqueue0\n[>]";
|
|
||||||
subgraph cluster_queue0_0x7f8f24028010_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
queue0_0x7f8f24028010_sink_0x7f8f268f0d50 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_queue0_0x7f8f24028010_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
queue0_0x7f8f24028010_src_0x7f8f268f0fa0 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb][T]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
queue0_0x7f8f24028010_sink_0x7f8f268f0d50 -> queue0_0x7f8f24028010_src_0x7f8f268f0fa0 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
queue0_0x7f8f24028010_src_0x7f8f268f0fa0 -> mux_0x7f8f23062190_sink_65_0x7f8f26012960 [label="video/x-h264\l stream-format: byte-stream\l alignment: au\l level: 3.1\l profile: main\l width: 1280\l height: 720\l pixel-aspect-ratio: 1/1\l framerate: 30/1\l interlace-mode: progressive\l colorimetry: bt709\l chroma-site: mpeg2\l multiview-mode: mono\l multiview-flags: 0:ffffffff:/right-view...\l"]
|
|
||||||
subgraph cluster_encoder_0x7f8f23059550 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstX264Enc\nencoder\n[>]\ntune=zerolatency";
|
|
||||||
subgraph cluster_encoder_0x7f8f23059550_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
encoder_0x7f8f23059550_sink_0x7f8f268f08b0 [color=black, fillcolor="#aaaaff", label="sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_encoder_0x7f8f23059550_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
encoder_0x7f8f23059550_src_0x7f8f268f0b00 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
encoder_0x7f8f23059550_sink_0x7f8f268f08b0 -> encoder_0x7f8f23059550_src_0x7f8f268f0b00 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
encoder_0x7f8f23059550_src_0x7f8f268f0b00 -> capsfilter1_0x7f8f2691e5d0_sink_0x7f8f23076e20 [label="video/x-h264\l stream-format: byte-stream\l alignment: au\l level: 3.1\l profile: main\l width: 1280\l height: 720\l pixel-aspect-ratio: 1/1\l framerate: 30/1\l interlace-mode: progressive\l colorimetry: bt709\l chroma-site: mpeg2\l multiview-mode: mono\l multiview-flags: 0:ffffffff:/right-view...\l"]
|
|
||||||
subgraph cluster_timeoverlay0_0x7f8f268f2a00 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstTimeOverlay\ntimeoverlay0\n[>]\nhalignment=left\nvalignment=top\ntext-x=29\ntext-y=31\ntext-width=304\ntext-height=38\ndatetime-epoch=((GDateTime*) 0x7f8f12d0e0e0)";
|
|
||||||
subgraph cluster_timeoverlay0_0x7f8f268f2a00_sink {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
timeoverlay0_0x7f8f268f2a00_video_sink_0x7f8f268f0410 [color=black, fillcolor="#aaaaff", label="video_sink\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_timeoverlay0_0x7f8f268f2a00_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
timeoverlay0_0x7f8f268f2a00_src_0x7f8f268f0660 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
timeoverlay0_0x7f8f268f2a00_video_sink_0x7f8f268f0410 -> timeoverlay0_0x7f8f268f2a00_src_0x7f8f268f0660 [style="invis"];
|
|
||||||
fillcolor="#aaffaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
timeoverlay0_0x7f8f268f2a00_src_0x7f8f268f0660 -> encoder_0x7f8f23059550_sink_0x7f8f268f08b0 [label="video/x-raw\l format: I420\l width: 1280\l height: 720\l framerate: 30/1\l multiview-mode: mono\l pixel-aspect-ratio: 1/1\l interlace-mode: progressive\l"]
|
|
||||||
subgraph cluster_videotestsrc0_0x7f8f268ec8e0 {
|
|
||||||
fontname="Bitstream Vera Sans";
|
|
||||||
fontsize="8";
|
|
||||||
style="filled,rounded";
|
|
||||||
color=black;
|
|
||||||
label="GstVideoTestSrc\nvideotestsrc0\n[>]\nis-live=TRUE";
|
|
||||||
subgraph cluster_videotestsrc0_0x7f8f268ec8e0_src {
|
|
||||||
label="";
|
|
||||||
style="invis";
|
|
||||||
videotestsrc0_0x7f8f268ec8e0_src_0x7f8f268f01c0 [color=black, fillcolor="#ffaaaa", label="src\n[>][bfb][T]", height="0.2", style="filled,solid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
fillcolor="#ffaaaa";
|
|
||||||
}
|
|
||||||
|
|
||||||
videotestsrc0_0x7f8f268ec8e0_src_0x7f8f268f01c0 -> capsfilter0_0x7f8f2691e290_sink_0x7f8f23076980 [label="video/x-raw\l format: I420\l width: 1280\l height: 720\l framerate: 30/1\l multiview-mode: mono\l pixel-aspect-ratio: 1/1\l interlace-mode: progressive\l"]
|
|
||||||
}
|
|
90
src/main.rs
90
src/main.rs
|
@ -1,5 +1,6 @@
|
||||||
|
use glib::translate::ToGlibPtr;
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
use log::info;
|
use log::{debug, info};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
@ -11,9 +12,10 @@ where
|
||||||
C: FnOnce() -> *mut gst_mpegts::GstMpegtsSCTESIT,
|
C: FnOnce() -> *mut gst_mpegts::GstMpegtsSCTESIT,
|
||||||
{
|
{
|
||||||
let sit = gst_sit();
|
let sit = gst_sit();
|
||||||
|
assert!(!sit.is_null());
|
||||||
unsafe {
|
unsafe {
|
||||||
let section = gst_mpegts::gst_mpegts_section_from_scte_sit(sit, 500);
|
let section = gst_mpegts::gst_mpegts_section_from_scte_sit(sit, 500);
|
||||||
gst_mpegts::gst_mpegts_section_send_event(section, element.as_ptr());
|
gst_mpegts::gst_mpegts_section_send_event(section, element.to_glib_none().0);
|
||||||
gst::ffi::gst_mini_object_unref(section as _);
|
gst::ffi::gst_mini_object_unref(section as _);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -36,6 +38,22 @@ fn send_splice_out(element: &gst::Element, event_id: u32, time: gst::ClockTime)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct EventId(Arc<Mutex<u32>>);
|
||||||
|
|
||||||
|
impl EventId {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Arc::new(Mutex::new(0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&self) -> u32 {
|
||||||
|
let mut counter = self.0.lock().unwrap();
|
||||||
|
*counter += 1;
|
||||||
|
*counter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() -> eyre::Result<()> {
|
fn main() -> eyre::Result<()> {
|
||||||
pretty_env_logger::init_timed();
|
pretty_env_logger::init_timed();
|
||||||
gst::init()?;
|
gst::init()?;
|
||||||
|
@ -43,14 +61,17 @@ fn main() -> eyre::Result<()> {
|
||||||
gst_mpegts::gst_mpegts_initialize();
|
gst_mpegts::gst_mpegts_initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ! rtpmp2tpay ! udpsink sync=true host=184.73.103.62 port=5000
|
||||||
let pipeline = gst::parse_launch(
|
let pipeline = gst::parse_launch(
|
||||||
r#"
|
r#"
|
||||||
|
|
||||||
|
audiotestsrc is-live=true ! audioconvert ! avenc_aac bitrate=128000 ! queue ! mux.
|
||||||
|
|
||||||
videotestsrc is-live=true ! video/x-raw,framerate=30/1,width=1280,height=720 ! timeoverlay ! x264enc tune=zerolatency name=encoder
|
videotestsrc is-live=true ! video/x-raw,framerate=30/1,width=1280,height=720 ! timeoverlay ! x264enc tune=zerolatency name=encoder
|
||||||
|
|
||||||
encoder. ! video/x-h264,profile=main ! queue ! mpegtsmux name=mux scte-35-pid=500 scte-35-null-interval=450000 alignment=7 ! rtpmp2tpay ! udpsink sync=true host=184.73.103.62 port=5000
|
encoder. ! video/x-h264,profile=main ! queue ! mpegtsmux name=mux scte-35-pid=500 scte-35-null-interval=450000
|
||||||
|
|
||||||
audiotestsrc is-live=true ! audioconvert ! avenc_aac bitrate=128000 ! queue ! mux.
|
mux. ! filesink sync=true location=out.ts
|
||||||
|
|
||||||
"#,
|
"#,
|
||||||
)?
|
)?
|
||||||
|
@ -59,12 +80,12 @@ fn main() -> eyre::Result<()> {
|
||||||
|
|
||||||
info!("Starting pipeline...");
|
info!("Starting pipeline...");
|
||||||
|
|
||||||
let ad_event_counter = Arc::new(Mutex::new(0u32));
|
let event_counter = EventId::new();
|
||||||
|
|
||||||
// Every 90 seconds we will loop on an ad scheduling process..
|
// Every 60 seconds we will loop on an ad scheduling process..
|
||||||
glib::timeout_add(Duration::from_secs(60), {
|
glib::timeout_add(Duration::from_secs(60), {
|
||||||
let pipeline_weak = pipeline.downgrade();
|
let pipeline_weak = pipeline.downgrade();
|
||||||
let ad_event_counter = ad_event_counter.clone();
|
let event_counter = event_counter.clone();
|
||||||
move || {
|
move || {
|
||||||
if let Some(pipeline) = pipeline_weak.upgrade() {
|
if let Some(pipeline) = pipeline_weak.upgrade() {
|
||||||
let muxer = pipeline.by_name("mux").unwrap();
|
let muxer = pipeline.by_name("mux").unwrap();
|
||||||
|
@ -73,39 +94,28 @@ fn main() -> eyre::Result<()> {
|
||||||
// is, so we use the pipeline running time to base our timing calculations
|
// is, so we use the pipeline running time to base our timing calculations
|
||||||
let now = pipeline.current_running_time().unwrap();
|
let now = pipeline.current_running_time().unwrap();
|
||||||
|
|
||||||
// How much ahead should the ad be inserted, we say 5 seconds in the future
|
// How much ahead should the ad be inserted, we say 0 seconds in the future (immediate)
|
||||||
let ahead = gst::ClockTime::from_seconds(0);
|
let ahead = gst::ClockTime::from_seconds(0);
|
||||||
|
|
||||||
// next event id
|
// Trigger the Splice Out event in the SCTE-35 stream
|
||||||
let event_id = {
|
send_splice_out(&muxer, event_counter.next(), now + ahead);
|
||||||
let mut ad_event_counter = ad_event_counter.lock().unwrap();
|
|
||||||
*ad_event_counter += 1;
|
|
||||||
*ad_event_counter
|
|
||||||
};
|
|
||||||
send_splice_out(&muxer, event_id, now + ahead);
|
|
||||||
|
|
||||||
// Now we add a timed call for the duration of the ad from now to indicate via
|
// Now we add a timed call for the duration of the ad from now to indicate via
|
||||||
// splice in that the stream can go back to normal programming.
|
// splice in that the stream can go back to normal programming.
|
||||||
glib::timeout_add(Duration::from_secs(30), {
|
glib::timeout_add(Duration::from_secs(30), {
|
||||||
let muxer_weak = muxer.downgrade();
|
let muxer_weak = muxer.downgrade();
|
||||||
let ad_event_counter = ad_event_counter.clone();
|
let event_counter = event_counter.clone();
|
||||||
move || {
|
move || {
|
||||||
if let Some(muxer) = muxer_weak.upgrade() {
|
if let Some(muxer) = muxer_weak.upgrade() {
|
||||||
// next event id
|
|
||||||
let event_id = {
|
|
||||||
let mut ad_event_counter = ad_event_counter.lock().unwrap();
|
|
||||||
*ad_event_counter += 1;
|
|
||||||
*ad_event_counter
|
|
||||||
};
|
|
||||||
let now = muxer.current_running_time().unwrap();
|
let now = muxer.current_running_time().unwrap();
|
||||||
send_splice_in(&muxer, event_id, now + ahead);
|
send_splice_in(&muxer, event_counter.next(), now + ahead);
|
||||||
}
|
}
|
||||||
// This don't need to run again
|
// This shall not run again
|
||||||
glib::Continue(false)
|
glib::Continue(false)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Run this again next time...
|
// Run this again after the timeout...
|
||||||
glib::Continue(true)
|
glib::Continue(true)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -118,6 +128,7 @@ fn main() -> eyre::Result<()> {
|
||||||
let bus = pipeline.bus().unwrap();
|
let bus = pipeline.bus().unwrap();
|
||||||
bus.add_watch({
|
bus.add_watch({
|
||||||
let main_loop = main_loop.clone();
|
let main_loop = main_loop.clone();
|
||||||
|
let pipeline_weak = pipeline.downgrade();
|
||||||
move |_, msg| {
|
move |_, msg| {
|
||||||
use gst::MessageView;
|
use gst::MessageView;
|
||||||
|
|
||||||
|
@ -133,6 +144,19 @@ fn main() -> eyre::Result<()> {
|
||||||
);
|
);
|
||||||
main_loop.quit();
|
main_loop.quit();
|
||||||
}
|
}
|
||||||
|
MessageView::StateChanged(s) => {
|
||||||
|
if let Some(pipeline) = pipeline_weak.upgrade() {
|
||||||
|
if s.src().map(|e| e == pipeline).unwrap_or(false) {
|
||||||
|
debug!("Writing dot file for status: {:?}", s.current());
|
||||||
|
|
||||||
|
let mut file = File::create(format!("Pipeline-{:?}.dot", s.current())).unwrap();
|
||||||
|
let dot_data = pipeline.debug_to_dot_data(
|
||||||
|
gst::DebugGraphDetails::all(),
|
||||||
|
);
|
||||||
|
file.write_all(dot_data.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,21 +166,9 @@ fn main() -> eyre::Result<()> {
|
||||||
.expect("Failed to add bus watch");
|
.expect("Failed to add bus watch");
|
||||||
|
|
||||||
ctrlc::set_handler({
|
ctrlc::set_handler({
|
||||||
let pipeline_weak = pipeline.downgrade();
|
let main_loop = main_loop.clone();
|
||||||
move || {
|
move || {
|
||||||
if let Some(pipeline) = pipeline_weak.upgrade() {
|
main_loop.quit();
|
||||||
pipeline.call_async(|itself| {
|
|
||||||
let dot_graph = itself
|
|
||||||
.debug_to_dot_data(gst::DebugGraphDetails::all())
|
|
||||||
.to_string();
|
|
||||||
let mut graph = File::create("pipeline.dot").unwrap();
|
|
||||||
graph.write_all(dot_graph.as_bytes()).unwrap();
|
|
||||||
|
|
||||||
itself.set_state(gst::State::Null).unwrap();
|
|
||||||
|
|
||||||
process::exit(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue