Update as per latest changes in upstream MR

Element has been renamed to hlsmultivariantsink. While at it,
allow testing H265 and MPEG-TS by specifying command line flag.
This commit is contained in:
Sanchayan Maity 2024-06-04 16:16:34 +05:30
parent 5806277012
commit bcbc533368
2 changed files with 124 additions and 43 deletions

View file

@ -15,7 +15,7 @@
height="480"
data-setup="{}"
>
<source src="http://localhost:8000/master.m3u8" type="application/x-mpegURL" />
<source src="http://localhost:8000/multivariant.m3u8" type="application/x-mpegURL" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that

View file

@ -1,4 +1,4 @@
use clap::{Parser, Subcommand};
use clap::{ArgAction, Parser, Subcommand};
use gst::glib;
use gst::prelude::*;
use once_cell::sync::Lazy;
@ -6,20 +6,24 @@ use std::str::FromStr;
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new(
"gst-hlssink4",
"gst-hlsmultivariantsink",
gst::DebugColorFlags::empty(),
Some("gst-hlssink4"),
)
});
#[derive(Parser)]
#[command(name = "gst-hlssink4")]
#[command(name = "gst-hlsmutivariantsink")]
#[command(version = "0.1")]
#[command(about = "Code for testing hlssink4", long_about = None)]
#[command(about = "Code for testing hlsmultivariantsink", long_about = None)]
struct Cli {
media_file_path: String,
#[command(subcommand)]
command: Option<Commands>,
#[arg(long, action=ArgAction::SetTrue)]
h265: bool,
#[arg(long, action=ArgAction::SetTrue)]
mpegts: bool,
}
#[derive(Subcommand)]
@ -108,7 +112,14 @@ fn file_source_bin(
(audiotee, videotee)
}
fn video_bin(width: u32, height: u32, fps: u32, bitrate: u32, iframe_only: bool) -> gst::Bin {
fn video_bin(
width: u32,
height: u32,
fps: u32,
bitrate: u32,
iframe_only: bool,
h265: bool,
) -> gst::Bin {
let bin = gst::Bin::new();
let clocksync = gst::ElementFactory::make("clocksync").build().unwrap();
@ -116,25 +127,39 @@ fn video_bin(width: u32, height: u32, fps: u32, bitrate: u32, iframe_only: bool)
let videoscale = gst::ElementFactory::make("videoscale").build().unwrap();
let videorate = gst::ElementFactory::make("videorate").build().unwrap();
let capsfilter = gst::ElementFactory::make("capsfilter").build().unwrap();
let x264enc = gst::ElementFactory::make("x264enc").build().unwrap();
let h264_capsfilter = gst::ElementFactory::make("capsfilter").build().unwrap();
let h264parse = gst::ElementFactory::make("h264parse").build().unwrap();
let x26xenc = if h265 {
gst::ElementFactory::make("x265enc").build().unwrap()
} else {
gst::ElementFactory::make("x264enc").build().unwrap()
};
let h26x_capsfilter = gst::ElementFactory::make("capsfilter").build().unwrap();
let h26xparse = if h265 {
gst::ElementFactory::make("h265parse").build().unwrap()
} else {
gst::ElementFactory::make("h264parse").build().unwrap()
};
let queue = gst::ElementFactory::make("queue").build().unwrap();
let caps = gst::Caps::from_str(format!("video/x-raw,width={width},height={height},framerate={fps}/1,pixel-aspect-ratio=1/1,format=I420").as_str()).unwrap();
capsfilter.set_property("caps", caps);
let caps = gst::Caps::from_str("video/x-h264").unwrap();
h264_capsfilter.set_property("caps", caps);
let caps = if h265 {
gst::Caps::from_str("video/x-h265").unwrap()
} else {
gst::Caps::from_str("video/x-h264").unwrap()
};
h26x_capsfilter.set_property("caps", caps);
x264enc.set_property("bitrate", bitrate);
x264enc.set_property_from_str("speed-preset", "ultrafast");
x264enc.set_property_from_str("tune", "zerolatency");
x26xenc.set_property("bitrate", bitrate);
x26xenc.set_property_from_str("speed-preset", "ultrafast");
x26xenc.set_property_from_str("tune", "zerolatency");
if iframe_only {
x264enc.set_property("key-int-max", 1);
x26xenc.set_property("key-int-max", 1);
} else if h265 {
x26xenc.set_property("key-int-max", (fps * 2) as i32);
} else {
x264enc.set_property("key-int-max", fps * 2);
x26xenc.set_property("key-int-max", fps * 2);
}
bin.add_many([
@ -143,9 +168,9 @@ fn video_bin(width: u32, height: u32, fps: u32, bitrate: u32, iframe_only: bool)
&videoscale,
&videorate,
&capsfilter,
&x264enc,
&h264_capsfilter,
&h264parse,
&x26xenc,
&h26x_capsfilter,
&h26xparse,
&queue,
])
.expect("failed to add the elements");
@ -156,9 +181,9 @@ fn video_bin(width: u32, height: u32, fps: u32, bitrate: u32, iframe_only: bool)
&videoscale,
&videorate,
&capsfilter,
&x264enc,
&h264_capsfilter,
&h264parse,
&x26xenc,
&h26x_capsfilter,
&h26xparse,
&queue,
])
.expect("failed to link the elements");
@ -237,14 +262,21 @@ fn multiple_audio_rendition_multiple_video_variant(
pipeline: &gst::Pipeline,
media_file_path: String,
iframe: bool,
h265: bool,
mpegts: bool,
) {
let hlssink = gst::ElementFactory::make("hlssink4").build().unwrap();
let hlssink = gst::ElementFactory::make("hlsmultivariantsink")
.build()
.unwrap();
hlssink.set_property("master-playlist-location", "hlssink/master.m3u8");
hlssink.set_property(
"multivariant-playlist-location",
"hlssink/multivariant.m3u8",
);
hlssink.set_property_from_str("playlist-type", "event");
hlssink.set_property("target-duration", 10u32);
if iframe {
hlssink.set_property_from_str("muxer-type", "mpegts")
if mpegts || iframe {
hlssink.set_property_from_str("muxer-type", "mpegts");
}
pipeline.add(&hlssink).unwrap();
@ -289,7 +321,7 @@ fn multiple_audio_rendition_multiple_video_variant(
audio2_pad.set_property("alternate-rendition", r);
audio_bin2_pad.link(&audio2_pad).unwrap();
let video_bin1 = video_bin(1920, 1080, 30, 2500, false);
let video_bin1 = video_bin(1920, 1080, 30, 2500, false, h265);
pipeline.add(&video_bin1).unwrap();
let video_bin1_sinkpad = video_bin1.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -304,7 +336,7 @@ fn multiple_audio_rendition_multiple_video_variant(
video1_pad.set_property("variant", v);
video_bin1_pad.link(&video1_pad).unwrap();
let video_bin2 = video_bin(1280, 720, 30, 1500, false);
let video_bin2 = video_bin(1280, 720, 30, 1500, false, h265);
pipeline.add(&video_bin2).unwrap();
let video_bin2_sinkpad = video_bin2.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -319,7 +351,7 @@ fn multiple_audio_rendition_multiple_video_variant(
video2_pad.set_property("variant", v);
video_bin2_pad.link(&video2_pad).unwrap();
let video_bin3 = video_bin(640, 360, 24, 700, false);
let video_bin3 = video_bin(640, 360, 24, 700, false, h265);
pipeline.add(&video_bin3).unwrap();
let video_bin3_sinkpad = video_bin3.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -342,12 +374,20 @@ fn multiple_audio_rendition_multiple_video_variant(
fn multiple_audio_rendition_single_video_variant(
pipeline: &gst::Pipeline,
media_file_path: String,
h265: bool,
mpegts: bool,
) {
let hlssink = gst::ElementFactory::make("hlssink4").build().unwrap();
hlssink.set_property("master-playlist-location", "hlssink/master.m3u8");
hlssink.set_property(
"multivariant-playlist-location",
"hlssink/multivariant.m3u8",
);
hlssink.set_property_from_str("playlist-type", "event");
hlssink.set_property("target-duration", 10u32);
if mpegts {
hlssink.set_property_from_str("muxer-type", "mpegts");
}
pipeline.add(&hlssink).unwrap();
@ -410,7 +450,7 @@ fn multiple_audio_rendition_single_video_variant(
audio3_pad.set_property("alternate-rendition", r);
audio_bin3_pad.link(&audio3_pad).unwrap();
let video_bin1 = video_bin(1920, 1080, 30, 2500, false);
let video_bin1 = video_bin(1920, 1080, 30, 2500, false, h265);
pipeline.add(&video_bin1).unwrap();
let video_bin1_sinkpad = video_bin1.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -429,12 +469,20 @@ fn multiple_audio_rendition_single_video_variant(
fn single_audio_rendition_multiple_video_variant(
pipeline: &gst::Pipeline,
media_file_path: String,
h265: bool,
mpegts: bool,
) {
let hlssink = gst::ElementFactory::make("hlssink4").build().unwrap();
hlssink.set_property("master-playlist-location", "hlssink/master.m3u8");
hlssink.set_property(
"multivariant-playlist-location",
"hlssink/multivariant.m3u8",
);
hlssink.set_property_from_str("playlist-type", "event");
hlssink.set_property("target-duration", 10u32);
if mpegts {
hlssink.set_property_from_str("muxer-type", "mpegts");
}
pipeline.add(&hlssink).unwrap();
@ -459,7 +507,7 @@ fn single_audio_rendition_multiple_video_variant(
audio1_pad.set_property("alternate-rendition", r);
audio_bin1_pad.link(&audio1_pad).unwrap();
let video_bin1 = video_bin(1920, 1080, 30, 2500, false);
let video_bin1 = video_bin(1920, 1080, 30, 2500, false, h265);
pipeline.add(&video_bin1).unwrap();
let video_bin1_sinkpad = video_bin1.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -474,7 +522,7 @@ fn single_audio_rendition_multiple_video_variant(
video1_pad.set_property("variant", v);
video_bin1_pad.link(&video1_pad).unwrap();
let video_bin2 = video_bin(1280, 720, 30, 1500, false);
let video_bin2 = video_bin(1280, 720, 30, 1500, false, h265);
pipeline.add(&video_bin2).unwrap();
let video_bin2_sinkpad = video_bin2.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -489,7 +537,7 @@ fn single_audio_rendition_multiple_video_variant(
video2_pad.set_property("variant", v);
video_bin2_pad.link(&video2_pad).unwrap();
let video_bin3 = video_bin(640, 360, 24, 700, false);
let video_bin3 = video_bin(640, 360, 24, 700, false, h265);
pipeline.add(&video_bin3).unwrap();
let video_bin3_sinkpad = video_bin3.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -508,10 +556,14 @@ fn single_audio_rendition_multiple_video_variant(
fn single_audio_only_variant_multiple_video_variant_with_audio_video_muxed(
pipeline: &gst::Pipeline,
media_file_path: String,
h265: bool,
) {
let hlssink = gst::ElementFactory::make("hlssink4").build().unwrap();
hlssink.set_property("master-playlist-location", "hlssink/master.m3u8");
hlssink.set_property(
"multivariant-playlist-location",
"hlssink/multivariant.m3u8",
);
hlssink.set_property_from_str("playlist-type", "event");
hlssink.set_property("target-duration", 10u32);
hlssink.set_property_from_str("muxer-type", "mpegts");
@ -520,7 +572,7 @@ fn single_audio_only_variant_multiple_video_variant_with_audio_video_muxed(
let (audiotee, videotee) = file_source_bin(pipeline, media_file_path);
let video_bin1 = video_bin(1920, 1080, 30, 2500, false);
let video_bin1 = video_bin(1920, 1080, 30, 2500, false, h265);
pipeline.add(&video_bin1).unwrap();
let video_bin1_sinkpad = video_bin1.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -535,7 +587,7 @@ fn single_audio_only_variant_multiple_video_variant_with_audio_video_muxed(
video1_pad.set_property("variant", v);
video_bin1_pad.link(&video1_pad).unwrap();
let video_bin2 = video_bin(1280, 720, 30, 1500, false);
let video_bin2 = video_bin(1280, 720, 30, 1500, false, h265);
pipeline.add(&video_bin2).unwrap();
let video_bin2_sinkpad = video_bin2.static_pad("sink").unwrap();
let videotee_srcpad = videotee.request_pad_simple("src_%u").unwrap();
@ -605,25 +657,48 @@ fn main() {
match cli.command {
Some(c @ Commands::MultipleAudioRenditionMultipleVideoVariant) => {
println!("Generating HLS playlist for: {:?}", c);
multiple_audio_rendition_multiple_video_variant(&pipeline, cli.media_file_path, false);
multiple_audio_rendition_multiple_video_variant(
&pipeline,
cli.media_file_path,
false,
cli.h265,
cli.mpegts,
);
}
Some(c @ Commands::MultipleAudioRenditionMultipleVideoVariantWithIframe) => {
println!("Generating HLS playlist for: {:?}", c);
multiple_audio_rendition_multiple_video_variant(&pipeline, cli.media_file_path, true);
multiple_audio_rendition_multiple_video_variant(
&pipeline,
cli.media_file_path,
true,
cli.h265,
cli.mpegts,
);
}
Some(c @ Commands::MultipleAudioRenditionSingleVideoVariant) => {
println!("Generating HLS playlist for: {:?}", c);
multiple_audio_rendition_single_video_variant(&pipeline, cli.media_file_path);
multiple_audio_rendition_single_video_variant(
&pipeline,
cli.media_file_path,
cli.h265,
cli.mpegts,
);
}
Some(c @ Commands::SingleAudioRenditionMultipleVideoVariant) => {
println!("Generating HLS playlist for: {:?}", c);
single_audio_rendition_multiple_video_variant(&pipeline, cli.media_file_path);
single_audio_rendition_multiple_video_variant(
&pipeline,
cli.media_file_path,
cli.h265,
cli.mpegts,
);
}
Some(c @ Commands::SingleAudioOnlyVariantMultipleVideoVariantWithAudioVideoMuxed) => {
println!("Generating HLS playlist for: {:?}", c);
single_audio_only_variant_multiple_video_variant_with_audio_video_muxed(
&pipeline,
cli.media_file_path,
cli.h265,
);
}
None => {
@ -631,7 +706,13 @@ fn main() {
"Generating HLS playlist for: {:?}",
Commands::MultipleAudioRenditionMultipleVideoVariant
);
multiple_audio_rendition_multiple_video_variant(&pipeline, cli.media_file_path, false);
multiple_audio_rendition_multiple_video_variant(
&pipeline,
cli.media_file_path,
false,
cli.mpegts,
cli.h265,
);
}
}