Fix cosmic-player file launch and video playback
Some checks failed
Validate .desktop files / validate (push) Has been cancelled
Some checks failed
Validate .desktop files / validate (push) Has been cancelled
This commit is contained in:
parent
4a1bfc975c
commit
e7781986f5
5 changed files with 67 additions and 22 deletions
2
build.rs
2
build.rs
|
|
@ -1,5 +1,5 @@
|
|||
use vergen::EmitBuilder;
|
||||
use std::{env, fs, path::PathBuf};
|
||||
use vergen::EmitBuilder;
|
||||
use xdgen::{App, Context, FluentString};
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ Exec=cosmic-player %U
|
|||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
MimeType=application/mxf;application/ram;application/sdp;application/vnd.apple.mpegurl;application/vnd.ms-asf;application/vnd.ms-wpl;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;application/x-extension-m4a;application/x-extension-mp4;application/x-flash-video;application/x-matroska;application/x-netshow-channel;application/x-quicktimeplayer;application/x-shorten;image/vnd.rn-realpix;image/x-pict;misc/ultravox;text/x-google-video-pointer;video/3gp;video/3gpp;video/3gpp2;video/dv;video/divx;video/fli;video/flv;video/mp2t;video/mp4;video/mp4v-es;video/mpeg;video/mpeg-system;video/msvideo;video/ogg;video/quicktime;video/vivo;video/vnd.divx;video/vnd.mpegurl;video/vnd.rn-realvideo;video/vnd.vivo;video/webm;video/x-anim;video/x-avi;video/x-flc;video/x-fli;video/x-flic;video/x-flv;video/x-m4v;video/x-matroska;video/x-mjpeg;video/x-mpeg;video/x-mpeg2;video/x-ms-asf;video/x-ms-asf-plugin;video/x-ms-asx;video/x-msvideo;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-nsv;video/x-ogm+ogg;video/x-theora;video/x-theora+ogg;video/x-totem-stream;audio/x-pn-realaudio;application/smil;application/smil+xml;application/x-quicktime-media-link;application/x-smil;text/google-video-pointer;x-content/video-dvd;x-scheme-handler/pnm;x-scheme-handler/mms;x-scheme-handler/net;x-scheme-handler/rtp;x-scheme-handler/rtmp;x-scheme-handler/rtsp;x-scheme-handler/mmsh;x-scheme-handler/uvox;x-scheme-handler/icy;x-scheme-handler/icyx;
|
||||
MimeType=application/mxf;application/ram;application/sdp;application/vnd.apple.mpegurl;application/vnd.ms-asf;application/vnd.ms-wpl;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;application/x-extension-m4a;application/x-extension-mp4;application/x-flash-video;application/x-matroska;application/x-netshow-channel;application/x-quicktimeplayer;application/x-shorten;image/vnd.rn-realpix;image/x-pict;misc/ultravox;text/x-google-video-pointer;video/3gp;video/3gpp;video/3gpp2;video/dv;video/divx;video/fli;video/flv;video/matroska;video/mp2t;video/mp4;video/mp4v-es;video/mpeg;video/mpeg-system;video/msvideo;video/ogg;video/quicktime;video/vivo;video/vnd.divx;video/vnd.mpegurl;video/vnd.rn-realvideo;video/vnd.vivo;video/webm;video/x-anim;video/x-avi;video/x-flc;video/x-fli;video/x-flic;video/x-flv;video/x-m4v;video/x-matroska;video/x-mjpeg;video/x-mpeg;video/x-mpeg2;video/x-ms-asf;video/x-ms-asf-plugin;video/x-ms-asx;video/x-msvideo;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-nsv;video/x-ogm+ogg;video/x-theora;video/x-theora+ogg;video/x-totem-stream;audio/x-pn-realaudio;application/smil;application/smil+xml;application/x-quicktime-media-link;application/x-smil;text/google-video-pointer;x-content/video-dvd;x-scheme-handler/pnm;x-scheme-handler/mms;x-scheme-handler/net;x-scheme-handler/rtp;x-scheme-handler/rtmp;x-scheme-handler/rtsp;x-scheme-handler/mmsh;x-scheme-handler/uvox;x-scheme-handler/icy;x-scheme-handler/icyx;
|
||||
Icon=com.system76.CosmicPlayer
|
||||
Categories=COSMIC;AudioVideo;Player;Video;
|
||||
Keywords=Audio;Film;Movie;Music;Sound;Video;
|
||||
|
|
|
|||
33
src/main.rs
33
src/main.rs
|
|
@ -8,10 +8,10 @@ use cosmic::iced::event::{self, Event};
|
|||
use cosmic::iced::keyboard::key::Physical;
|
||||
use cosmic::iced::keyboard::{Event as KeyEvent, Key, Modifiers};
|
||||
use cosmic::iced::mouse::{Event as MouseEvent, ScrollDelta};
|
||||
use cosmic::iced::window::set_mode;
|
||||
use cosmic::iced::{
|
||||
Alignment, Background, Border, Color, ContentFit, Length, Limits, Subscription, exit, window,
|
||||
};
|
||||
use cosmic::iced::window::set_mode;
|
||||
use cosmic::widget::menu::action::MenuAction;
|
||||
use cosmic::widget::{self, Slider, about::About, nav_bar, segmented_button};
|
||||
use cosmic::{Application, ApplicationExt, Element, action, cosmic_theme, executor, font, theme};
|
||||
|
|
@ -107,16 +107,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "redox")))]
|
||||
match fork::daemon(true, true) {
|
||||
Ok(fork::Fork::Child) => (),
|
||||
Ok(fork::Fork::Parent(_child_pid)) => process::exit(0),
|
||||
Err(err) => {
|
||||
eprintln!("failed to daemonize: {:?}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
localize::localize();
|
||||
|
||||
let config = match cosmic_config::Config::new(App::APP_ID, CONFIG_VERSION) {
|
||||
|
|
@ -169,6 +159,18 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn stream_tags(pipeline: &gst::Pipeline, signal: &str, stream: i32) -> Option<gst::TagList> {
|
||||
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||
pipeline.emit_by_name::<Option<gst::TagList>>(signal, &[&stream])
|
||||
})) {
|
||||
Ok(tags) => tags,
|
||||
Err(_) => {
|
||||
log::warn!("failed to read {signal} for stream {stream}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Action {
|
||||
About,
|
||||
|
|
@ -417,14 +419,15 @@ impl App {
|
|||
|
||||
let n_video = pipeline.property::<i32>("n-video");
|
||||
for i in 0..n_video {
|
||||
let tags: gst::TagList = pipeline.emit_by_name("get-video-tags", &[&i]);
|
||||
log::info!("video stream {i}: {tags:#?}");
|
||||
if let Some(tags) = stream_tags(&pipeline, "get-video-tags", i) {
|
||||
log::info!("video stream {i}: {tags:#?}");
|
||||
}
|
||||
}
|
||||
|
||||
let n_audio = pipeline.property::<i32>("n-audio");
|
||||
self.audio_codes = Vec::with_capacity(n_audio as usize);
|
||||
for i in 0..n_audio {
|
||||
let tags: gst::TagList = pipeline.emit_by_name("get-audio-tags", &[&i]);
|
||||
let tags = stream_tags(&pipeline, "get-audio-tags", i).unwrap_or_default();
|
||||
log::info!("audio stream {i}: {tags:#?}");
|
||||
self.audio_codes
|
||||
.push(if let Some(title) = tags.get::<gst::tags::Title>() {
|
||||
|
|
@ -446,7 +449,7 @@ impl App {
|
|||
name: fl!("off"),
|
||||
});
|
||||
for i in 0..n_text {
|
||||
let tags: gst::TagList = pipeline.emit_by_name("get-text-tags", &[&i]);
|
||||
let tags = stream_tags(&pipeline, "get-text-tags", i).unwrap_or_default();
|
||||
log::info!("text stream {i}: {tags:#?}");
|
||||
let name = if let Some(title) = tags.get::<gst::tags::Title>() {
|
||||
title.get().to_string()
|
||||
|
|
|
|||
31
src/video.rs
31
src/video.rs
|
|
@ -16,11 +16,17 @@ pub fn new_video(
|
|||
//TODO: this code came from iced_video_player::Video::new and has been modified to stop the pipeline on error
|
||||
//TODO: remove unwraps and enable playback of files with only audio.
|
||||
gst::init().unwrap();
|
||||
disable_broken_hardware_decoders();
|
||||
|
||||
let pipeline = format!(
|
||||
"playbin uri=\"{}\"{} video-sink=\"videoscale ! videoconvert ! videoflip method=automatic ! appsink name=iced_video drop=true caps=video/x-raw,format=NV12,pixel-aspect-ratio=1/1\"",
|
||||
"playbin uri=\"{}\"{}{} video-sink=\"videoscale ! videoconvert ! videoflip method=automatic ! appsink name=iced_video drop=true caps=video/x-raw,format=NV12,pixel-aspect-ratio=1/1\"",
|
||||
url.as_str(),
|
||||
if settings.mute { " mute=true" } else { "" }
|
||||
if settings.mute { " mute=true" } else { "" },
|
||||
if settings.mute {
|
||||
" audio-sink=fakesink"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
);
|
||||
let pipeline = gst::parse::launch(pipeline.as_ref())
|
||||
.unwrap()
|
||||
|
|
@ -84,3 +90,24 @@ pub fn new_video(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn disable_broken_hardware_decoders() {
|
||||
let registry = gst::Registry::get();
|
||||
for decoder in [
|
||||
"nvav1dec",
|
||||
"nvh264dec",
|
||||
"nvh265dec",
|
||||
"nvjpegdec",
|
||||
"nvmpeg2videodec",
|
||||
"nvmpeg4videodec",
|
||||
"nvmpegvideodec",
|
||||
"nvvp8dec",
|
||||
"nvvp9dec",
|
||||
] {
|
||||
if let Some(feature) = registry.lookup_feature(decoder) {
|
||||
let rank = feature.rank();
|
||||
feature.set_rank(gst::Rank::NONE);
|
||||
log::debug!("disabled GStreamer decoder {decoder} with rank {rank:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
21
vendor/iced_video_player/src/video.rs
vendored
21
vendor/iced_video_player/src/video.rs
vendored
|
|
@ -277,9 +277,21 @@ impl Video {
|
|||
// wait for up to 5 seconds until the decoder gets the source capabilities
|
||||
pipeline.state(gst::ClockTime::from_seconds(5)).0?;
|
||||
|
||||
let mut initial_sample = None;
|
||||
let caps = pad.current_caps().or_else(|| {
|
||||
let sample = video_sink
|
||||
.try_pull_preroll(gst::ClockTime::from_seconds(2))
|
||||
.or_else(|| video_sink.try_pull_sample(gst::ClockTime::from_seconds(2)))?;
|
||||
let caps = sample.caps().map(|caps| caps.to_owned());
|
||||
if sample.buffer().is_some() {
|
||||
initial_sample = Some(sample);
|
||||
}
|
||||
caps
|
||||
});
|
||||
|
||||
// extract resolution and framerate
|
||||
// TODO(jazzfool): maybe we want to extract some other information too?
|
||||
let (width, height, framerate, has_video) = if let Some(caps) = pad.current_caps() {
|
||||
let (width, height, framerate, has_video) = if let Some(caps) = caps {
|
||||
let s = caps.structure(0).ok_or(Error::Caps)?;
|
||||
let width = s.get::<i32>("width").map_err(|_| Error::Caps)?;
|
||||
let height = s.get::<i32>("height").map_err(|_| Error::Caps)?;
|
||||
|
|
@ -313,8 +325,11 @@ impl Video {
|
|||
let sync_av = pipeline.has_property("av-offset");
|
||||
|
||||
// NV12 = 12bpp
|
||||
let frame = Arc::new(Mutex::new(Frame::new()));
|
||||
let upload_frame = Arc::new(AtomicBool::new(false));
|
||||
let has_initial_sample = initial_sample.is_some();
|
||||
let frame = Arc::new(Mutex::new(
|
||||
initial_sample.map(Frame).unwrap_or_else(Frame::new),
|
||||
));
|
||||
let upload_frame = Arc::new(AtomicBool::new(has_initial_sample));
|
||||
let alive = Arc::new(AtomicBool::new(true));
|
||||
let last_frame_time = Arc::new(Mutex::new(Instant::now()));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue