Implement ClockTime as ClockTime(Option<u64>)

And also implement a FormatValue type that holds a value together with
its format to make usage of the positions/durations/seek positions/etc
more convenient and safe.

Fixes https://github.com/sdroege/gstreamer-rs/issues/3
This commit is contained in:
Sebastian Dröge 2017-11-11 11:21:55 +01:00
parent bdcf0246eb
commit c39c0c7264
39 changed files with 1174 additions and 386 deletions

View file

@ -14,7 +14,6 @@ external_libraries = [
]
generate = [
"Gst.ClockTime",
"Gst.ClockTimeDiff",
"Gst.Pipeline",
"Gst.State",
@ -83,6 +82,11 @@ manual = [
"Gst.StaticPadTemplate",
]
[[object]]
name = "Gst.ClockTime"
status = "manual"
conversion_type = "scalar"
[[object]]
name = "Gst.Bin"
status = "generate"
@ -312,6 +316,31 @@ status = "generate"
# ulong
ignore = true
[[object.function]]
name = "query_duration"
# formatted value
ignore = true
[[object.function]]
name = "query_position"
# formatted value
ignore = true
[[object.function]]
name = "query_convert"
# formatted value
ignore = true
[[object.function]]
name = "seek"
# formatted value
ignore = true
[[object.function]]
name = "seek_simple"
# formatted value
ignore = true
[[object]]
name = "Gst.ElementFactory"
status = "generate"

View file

@ -24,7 +24,6 @@ manual = [
"Gst.Object",
"Gst.Element",
"Gst.URIHandler",
"Gst.ClockTime",
"Gst.FlowReturn",
"Gst.Format",
"GstBase.BaseSrc",
@ -100,3 +99,8 @@ ref_mode = "ref"
name = "Gst.Sample"
status = "manual"
ref_mode = "ref"
[[object]]
name = "Gst.ClockTime"
status = "manual"
conversion_type = "scalar"

View file

@ -26,7 +26,6 @@ manual = [
"GLib.Bytes",
"Gst.Object",
"Gst.Element",
"Gst.ClockTime",
"Gst.ClockTimeDiff",
"Gst.ClockReturn",
"Gst.FlowReturn",
@ -96,3 +95,8 @@ ref_mode = "ref"
name = "Gst.Sample"
status = "manual"
ref_mode = "ref"
[[object]]
name = "Gst.ClockTime"
status = "manual"
conversion_type = "scalar"

View file

@ -28,7 +28,6 @@ manual = [
"GLib.Error",
"GLib.MainContext",
"GObject.Object",
"Gst.ClockTime",
"Gst.Element",
]
@ -158,3 +157,8 @@ trait = false
name = "new"
# Wrong return value
ignore = true
[[object]]
name = "Gst.ClockTime"
status = "manual"
conversion_type = "scalar"

View file

@ -59,25 +59,14 @@ fn create_ui(app: &gtk::Application) {
let pipeline_clone = pipeline.clone();
gtk::timeout_add(500, move || {
let pipeline = &pipeline_clone;
let position = pipeline.query_position(gst::Format::Time);
if let Some(position) = position {
let mut seconds = (position as gst::ClockTime) / gst::SECOND;
let mut minutes = seconds / 60;
let hours = minutes / 60;
seconds %= 60;
minutes %= 60;
label.set_text(&format!(
"Position: {:02}:{:02}:{:02}",
hours,
minutes,
seconds
));
let position = if let Some(gst::FormatValue::Time(position)) =
pipeline.query_position(gst::Format::Time)
{
position
} else {
label.set_text("Position: 00:00:00");
}
0.into()
};
label.set_text(&format!("Position: {:.0}", position));
glib::Continue(true)
});

View file

@ -129,25 +129,14 @@ fn create_ui(app: &gtk::Application) {
let pipeline_clone = pipeline.clone();
gtk::timeout_add(500, move || {
let pipeline = &pipeline_clone;
let position = pipeline.query_position(gst::Format::Time);
if let Some(position) = position {
let mut seconds = (position as gst::ClockTime) / gst::SECOND;
let mut minutes = seconds / 60;
let hours = minutes / 60;
seconds %= 60;
minutes %= 60;
label.set_text(&format!(
"Position: {:02}:{:02}:{:02}",
hours,
minutes,
seconds
));
let position = if let Some(gst::FormatValue::Time(position)) =
pipeline.query_position(gst::Format::Time)
{
position
} else {
label.set_text("Position: 00:00:00");
}
0.into()
};
label.set_text(&format!("Position: {:.0}", position));
glib::Continue(true)
});

View file

@ -30,21 +30,29 @@ fn main() {
//let dur = pipeline.query_duration(gst::Format::Time).unwrap_or(-1);
let pos = {
let mut q = gst::Query::new_position(gst::Format::Time);
pipeline.query(q.get_mut().unwrap());
if pipeline.query(q.get_mut().unwrap()) {
match q.view() {
QueryView::Position(ref p) => p.get().1,
_ => unreachable!(),
QueryView::Position(ref p) => Some(p.get()),
_ => None,
}
};
} else {
None
}
}.and_then(|pos| pos.try_to_time())
.unwrap();
let dur = {
let mut q = gst::Query::new_duration(gst::Format::Time);
pipeline.query(q.get_mut().unwrap());
if pipeline.query(q.get_mut().unwrap()) {
match q.view() {
QueryView::Duration(ref p) => p.get().1,
_ => unreachable!(),
QueryView::Duration(ref p) => Some(p.get()),
_ => None,
}
};
} else {
None
}
}.and_then(|dur| dur.try_to_time())
.unwrap();
println!("{} / {}", pos, dur);

View file

@ -130,14 +130,14 @@ impl AppSink {
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub fn try_pull_preroll(&self, timeout: gst::ClockTime) -> Option<gst::Sample> {
unsafe {
from_glib_full(ffi::gst_app_sink_try_pull_preroll(self.to_glib_none().0, timeout))
from_glib_full(ffi::gst_app_sink_try_pull_preroll(self.to_glib_none().0, timeout.to_glib()))
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub fn try_pull_sample(&self, timeout: gst::ClockTime) -> Option<gst::Sample> {
unsafe {
from_glib_full(ffi::gst_app_sink_try_pull_sample(self.to_glib_none().0, timeout))
from_glib_full(ffi::gst_app_sink_try_pull_sample(self.to_glib_none().0, timeout.to_glib()))
}
}

View file

@ -54,7 +54,7 @@ impl AppSrc {
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub fn get_duration(&self) -> gst::ClockTime {
unsafe {
ffi::gst_app_src_get_duration(self.to_glib_none().0)
from_glib(ffi::gst_app_src_get_duration(self.to_glib_none().0))
}
}
@ -110,7 +110,7 @@ impl AppSrc {
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub fn set_duration(&self, duration: gst::ClockTime) {
unsafe {
ffi::gst_app_src_set_duration(self.to_glib_none().0, duration);
ffi::gst_app_src_set_duration(self.to_glib_none().0, duration.to_glib());
}
}

View file

@ -42,12 +42,13 @@ impl<'a> AudioInfoBuilder<'a> {
return None;
}
let positions: [ffi::GstAudioChannelPosition; 64] =
array_init::array_init_copy(|i| if i >= self.channels as usize {
let positions: [ffi::GstAudioChannelPosition; 64] = array_init::array_init_copy(
|i| if i >= self.channels as usize {
ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
} else {
p[i].to_glib()
});
},
);
let valid: bool = from_glib(ffi::gst_audio_check_valid_channel_positions(
positions.as_ptr() as *mut _,
@ -156,22 +157,21 @@ impl AudioInfo {
pub fn convert(
&self,
src_fmt: gst::Format,
src_val: i64,
src_val: gst::FormatValue,
dest_fmt: gst::Format,
) -> Option<i64> {
) -> Option<gst::FormatValue> {
assert_initialized_main_thread!();
unsafe {
let mut dest_val = mem::uninitialized();
if from_glib(ffi::gst_audio_info_convert(
&self.0,
src_fmt.to_glib(),
src_val,
src_val.to_format().to_glib(),
src_val.to_value(),
dest_fmt.to_glib(),
&mut dest_val,
)) {
Some(dest_val)
Some(gst::FormatValue::new(dest_fmt, dest_val))
} else {
None
}

View file

@ -59,7 +59,7 @@ impl Adapter {
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub fn dts_at_discont(&self) -> gst::ClockTime {
unsafe {
ffi::gst_adapter_dts_at_discont(self.to_glib_none().0)
from_glib(ffi::gst_adapter_dts_at_discont(self.to_glib_none().0))
}
}
@ -117,7 +117,7 @@ impl Adapter {
pub fn prev_dts(&self) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_dts(self.to_glib_none().0, &mut distance);
let ret = from_glib(ffi::gst_adapter_prev_dts(self.to_glib_none().0, &mut distance));
(ret, distance)
}
}
@ -125,7 +125,7 @@ impl Adapter {
pub fn prev_dts_at_offset(&self, offset: usize) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_dts_at_offset(self.to_glib_none().0, offset, &mut distance);
let ret = from_glib(ffi::gst_adapter_prev_dts_at_offset(self.to_glib_none().0, offset, &mut distance));
(ret, distance)
}
}
@ -142,7 +142,7 @@ impl Adapter {
pub fn prev_pts(&self) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_pts(self.to_glib_none().0, &mut distance);
let ret = from_glib(ffi::gst_adapter_prev_pts(self.to_glib_none().0, &mut distance));
(ret, distance)
}
}
@ -150,7 +150,7 @@ impl Adapter {
pub fn prev_pts_at_offset(&self, offset: usize) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_pts_at_offset(self.to_glib_none().0, offset, &mut distance);
let ret = from_glib(ffi::gst_adapter_prev_pts_at_offset(self.to_glib_none().0, offset, &mut distance));
(ret, distance)
}
}
@ -158,7 +158,7 @@ impl Adapter {
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub fn pts_at_discont(&self) -> gst::ClockTime {
unsafe {
ffi::gst_adapter_pts_at_discont(self.to_glib_none().0)
from_glib(ffi::gst_adapter_pts_at_discont(self.to_glib_none().0))
}
}

View file

@ -154,7 +154,7 @@ impl<O: IsA<BaseSink> + IsA<glib::object::Object>> BaseSinkExt for O {
fn get_latency(&self) -> gst::ClockTime {
unsafe {
ffi::gst_base_sink_get_latency(self.to_glib_none().0)
from_glib(ffi::gst_base_sink_get_latency(self.to_glib_none().0))
}
}
@ -172,7 +172,7 @@ impl<O: IsA<BaseSink> + IsA<glib::object::Object>> BaseSinkExt for O {
fn get_render_delay(&self) -> gst::ClockTime {
unsafe {
ffi::gst_base_sink_get_render_delay(self.to_glib_none().0)
from_glib(ffi::gst_base_sink_get_render_delay(self.to_glib_none().0))
}
}
@ -219,7 +219,7 @@ impl<O: IsA<BaseSink> + IsA<glib::object::Object>> BaseSinkExt for O {
let mut min_latency = mem::uninitialized();
let mut max_latency = mem::uninitialized();
let ret = from_glib(ffi::gst_base_sink_query_latency(self.to_glib_none().0, &mut live, &mut upstream_live, &mut min_latency, &mut max_latency));
if ret { Some((from_glib(live), from_glib(upstream_live), min_latency, max_latency)) } else { None }
if ret { Some((from_glib(live), from_glib(upstream_live), from_glib(min_latency), from_glib(max_latency))) } else { None }
}
}
@ -268,7 +268,7 @@ impl<O: IsA<BaseSink> + IsA<glib::object::Object>> BaseSinkExt for O {
fn set_render_delay(&self, delay: gst::ClockTime) {
unsafe {
ffi::gst_base_sink_set_render_delay(self.to_glib_none().0, delay);
ffi::gst_base_sink_set_render_delay(self.to_glib_none().0, delay.to_glib());
}
}
@ -293,7 +293,7 @@ impl<O: IsA<BaseSink> + IsA<glib::object::Object>> BaseSinkExt for O {
fn wait(&self, time: gst::ClockTime) -> (gst::FlowReturn, gst::ClockTimeDiff) {
unsafe {
let mut jitter = mem::uninitialized();
let ret = from_glib(ffi::gst_base_sink_wait(self.to_glib_none().0, time, &mut jitter));
let ret = from_glib(ffi::gst_base_sink_wait(self.to_glib_none().0, time.to_glib(), &mut jitter));
(ret, jitter)
}
}
@ -301,7 +301,7 @@ impl<O: IsA<BaseSink> + IsA<glib::object::Object>> BaseSinkExt for O {
fn wait_clock(&self, time: gst::ClockTime) -> (gst::ClockReturn, gst::ClockTimeDiff) {
unsafe {
let mut jitter = mem::uninitialized();
let ret = from_glib(ffi::gst_base_sink_wait_clock(self.to_glib_none().0, time, &mut jitter));
let ret = from_glib(ffi::gst_base_sink_wait_clock(self.to_glib_none().0, time.to_glib(), &mut jitter));
(ret, jitter)
}
}

View file

@ -133,7 +133,7 @@ impl<O: IsA<BaseSrc> + IsA<glib::object::Object>> BaseSrcExt for O {
let mut min_latency = mem::uninitialized();
let mut max_latency = mem::uninitialized();
let ret = from_glib(ffi::gst_base_src_query_latency(self.to_glib_none().0, &mut live, &mut min_latency, &mut max_latency));
if ret { Some((from_glib(live), min_latency, max_latency)) } else { None }
if ret { Some((from_glib(live), from_glib(min_latency), from_glib(max_latency))) } else { None }
}
}

View file

@ -139,7 +139,7 @@ impl<O: IsA<BaseTransform> + IsA<glib::object::Object>> BaseTransformExt for O {
fn update_qos(&self, proportion: f64, diff: gst::ClockTimeDiff, timestamp: gst::ClockTime) {
unsafe {
ffi::gst_base_transform_update_qos(self.to_glib_none().0, proportion, diff, timestamp);
ffi::gst_base_transform_update_qos(self.to_glib_none().0, proportion, diff, timestamp.to_glib());
}
}

View file

@ -83,7 +83,7 @@ impl Player {
pub fn get_duration(&self) -> gst::ClockTime {
unsafe {
ffi::gst_player_get_duration(self.to_glib_none().0)
from_glib(ffi::gst_player_get_duration(self.to_glib_none().0))
}
}
@ -115,7 +115,7 @@ impl Player {
pub fn get_position(&self) -> gst::ClockTime {
unsafe {
ffi::gst_player_get_position(self.to_glib_none().0)
from_glib(ffi::gst_player_get_position(self.to_glib_none().0))
}
}
@ -171,7 +171,7 @@ impl Player {
pub fn seek(&self, position: gst::ClockTime) {
unsafe {
ffi::gst_player_seek(self.to_glib_none().0, position);
ffi::gst_player_seek(self.to_glib_none().0, position.to_glib());
}
}

View file

@ -36,7 +36,7 @@ impl PlayerMediaInfo {
pub fn get_duration(&self) -> gst::ClockTime {
unsafe {
ffi::gst_player_media_info_get_duration(self.to_glib_none().0)
from_glib(ffi::gst_player_media_info_get_duration(self.to_glib_none().0))
}
}

View file

@ -545,24 +545,25 @@ impl VideoInfo {
self.format_info().n_components()
}
pub fn convert(
pub fn convert<V: Into<gst::FormatValue>>(
&self,
src_fmt: gst::Format,
src_val: i64,
src_val: V,
dest_fmt: gst::Format,
) -> Option<i64> {
) -> Option<gst::FormatValue> {
skip_assert_initialized!();
let src_val = src_val.into();
unsafe {
let mut dest_val = mem::uninitialized();
if from_glib(ffi::gst_video_info_convert(
&self.0 as *const _ as *mut _,
src_fmt.to_glib(),
src_val,
src_val.to_format().to_glib(),
src_val.to_value(),
dest_fmt.to_glib(),
&mut dest_val,
)) {
Some(dest_val)
Some(gst::FormatValue::new(dest_fmt, dest_val))
} else {
None
}

View file

@ -22,6 +22,7 @@ glib = { git = "https://github.com/gtk-rs/glib" }
num-rational = { version = "0.1.38", default-features = false, features = [] }
lazy_static = "0.2"
futures = { version = "0.1", optional = true }
muldiv = "0.1.1"
[build-dependencies.rustdoc-stripper]
version = "0.1"

View file

@ -4,6 +4,5 @@
#[allow(unused_imports)]
use auto::*;
pub type ClockTime = u64;
pub type ClockTimeDiff = i64;
pub type ElementFactoryListType = u64;

View file

@ -113,7 +113,7 @@ impl Bus {
pub fn timed_pop(&self, timeout: ClockTime) -> Option<Message> {
unsafe {
from_glib_full(ffi::gst_bus_timed_pop(self.to_glib_none().0, timeout))
from_glib_full(ffi::gst_bus_timed_pop(self.to_glib_none().0, timeout.to_glib()))
}
}

View file

@ -127,7 +127,7 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
fn add_observation(&self, slave: ClockTime, master: ClockTime) -> Option<f64> {
unsafe {
let mut r_squared = mem::uninitialized();
let ret = from_glib(ffi::gst_clock_add_observation(self.to_glib_none().0, slave, master, &mut r_squared));
let ret = from_glib(ffi::gst_clock_add_observation(self.to_glib_none().0, slave.to_glib(), master.to_glib(), &mut r_squared));
if ret { Some(r_squared) } else { None }
}
}
@ -139,20 +139,20 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
let mut external = mem::uninitialized();
let mut rate_num = mem::uninitialized();
let mut rate_denom = mem::uninitialized();
let ret = from_glib(ffi::gst_clock_add_observation_unapplied(self.to_glib_none().0, slave, master, &mut r_squared, &mut internal, &mut external, &mut rate_num, &mut rate_denom));
if ret { Some((r_squared, internal, external, rate_num, rate_denom)) } else { None }
let ret = from_glib(ffi::gst_clock_add_observation_unapplied(self.to_glib_none().0, slave.to_glib(), master.to_glib(), &mut r_squared, &mut internal, &mut external, &mut rate_num, &mut rate_denom));
if ret { Some((r_squared, from_glib(internal), from_glib(external), from_glib(rate_num), from_glib(rate_denom))) } else { None }
}
}
fn adjust_unlocked(&self, internal: ClockTime) -> ClockTime {
unsafe {
ffi::gst_clock_adjust_unlocked(self.to_glib_none().0, internal)
from_glib(ffi::gst_clock_adjust_unlocked(self.to_glib_none().0, internal.to_glib()))
}
}
fn adjust_with_calibration(&self, internal_target: ClockTime, cinternal: ClockTime, cexternal: ClockTime, cnum: ClockTime, cdenom: ClockTime) -> ClockTime {
unsafe {
ffi::gst_clock_adjust_with_calibration(self.to_glib_none().0, internal_target, cinternal, cexternal, cnum, cdenom)
from_glib(ffi::gst_clock_adjust_with_calibration(self.to_glib_none().0, internal_target.to_glib(), cinternal.to_glib(), cexternal.to_glib(), cnum.to_glib(), cdenom.to_glib()))
}
}
@ -163,13 +163,13 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
let mut rate_num = mem::uninitialized();
let mut rate_denom = mem::uninitialized();
ffi::gst_clock_get_calibration(self.to_glib_none().0, &mut internal, &mut external, &mut rate_num, &mut rate_denom);
(internal, external, rate_num, rate_denom)
(from_glib(internal), from_glib(external), from_glib(rate_num), from_glib(rate_denom))
}
}
fn get_internal_time(&self) -> ClockTime {
unsafe {
ffi::gst_clock_get_internal_time(self.to_glib_none().0)
from_glib(ffi::gst_clock_get_internal_time(self.to_glib_none().0))
}
}
@ -181,19 +181,19 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
fn get_resolution(&self) -> ClockTime {
unsafe {
ffi::gst_clock_get_resolution(self.to_glib_none().0)
from_glib(ffi::gst_clock_get_resolution(self.to_glib_none().0))
}
}
fn get_time(&self) -> ClockTime {
unsafe {
ffi::gst_clock_get_time(self.to_glib_none().0)
from_glib(ffi::gst_clock_get_time(self.to_glib_none().0))
}
}
fn get_timeout(&self) -> ClockTime {
unsafe {
ffi::gst_clock_get_timeout(self.to_glib_none().0)
from_glib(ffi::gst_clock_get_timeout(self.to_glib_none().0))
}
}
@ -217,7 +217,7 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
fn set_calibration(&self, internal: ClockTime, external: ClockTime, rate_num: ClockTime, rate_denom: ClockTime) {
unsafe {
ffi::gst_clock_set_calibration(self.to_glib_none().0, internal, external, rate_num, rate_denom);
ffi::gst_clock_set_calibration(self.to_glib_none().0, internal.to_glib(), external.to_glib(), rate_num.to_glib(), rate_denom.to_glib());
}
}
@ -231,7 +231,7 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
fn set_resolution(&self, resolution: ClockTime) -> ClockTime {
unsafe {
ffi::gst_clock_set_resolution(self.to_glib_none().0, resolution)
from_glib(ffi::gst_clock_set_resolution(self.to_glib_none().0, resolution.to_glib()))
}
}
@ -243,7 +243,7 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
fn set_timeout(&self, timeout: ClockTime) {
unsafe {
ffi::gst_clock_set_timeout(self.to_glib_none().0, timeout);
ffi::gst_clock_set_timeout(self.to_glib_none().0, timeout.to_glib());
}
}
@ -253,19 +253,19 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExt for O {
fn unadjust_unlocked(&self, external: ClockTime) -> ClockTime {
unsafe {
ffi::gst_clock_unadjust_unlocked(self.to_glib_none().0, external)
from_glib(ffi::gst_clock_unadjust_unlocked(self.to_glib_none().0, external.to_glib()))
}
}
fn unadjust_with_calibration(&self, external_target: ClockTime, cinternal: ClockTime, cexternal: ClockTime, cnum: ClockTime, cdenom: ClockTime) -> ClockTime {
unsafe {
ffi::gst_clock_unadjust_with_calibration(self.to_glib_none().0, external_target, cinternal, cexternal, cnum, cdenom)
from_glib(ffi::gst_clock_unadjust_with_calibration(self.to_glib_none().0, external_target.to_glib(), cinternal.to_glib(), cexternal.to_glib(), cnum.to_glib(), cdenom.to_glib()))
}
}
fn wait_for_sync(&self, timeout: ClockTime) -> Result<(), glib::error::BoolError> {
unsafe {
glib::error::BoolError::from_glib(ffi::gst_clock_wait_for_sync(self.to_glib_none().0, timeout), "Timed out waiting for sync")
glib::error::BoolError::from_glib(ffi::gst_clock_wait_for_sync(self.to_glib_none().0, timeout.to_glib()), "Timed out waiting for sync")
}
}

View file

@ -8,15 +8,12 @@ use ClockTime;
use Context;
use ElementFactory;
use Error;
use Format;
use Message;
use Object;
use Pad;
use PadLinkCheck;
use PadTemplate;
use Plugin;
use SeekFlags;
use SeekType;
use State;
use StateChange;
use StateChangeReturn;
@ -153,22 +150,12 @@ pub trait ElementExt {
fn provide_clock(&self) -> Option<Clock>;
fn query_convert(&self, src_format: Format, src_val: i64, dest_format: Format) -> Option<i64>;
fn query_duration(&self, format: Format) -> Option<i64>;
fn query_position(&self, format: Format) -> Option<i64>;
fn release_request_pad<P: IsA<Pad>>(&self, pad: &P);
fn remove_pad<P: IsA<Pad>>(&self, pad: &P) -> Result<(), glib::error::BoolError>;
fn request_pad<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b Caps>>>(&self, templ: &PadTemplate, name: P, caps: Q) -> Option<Pad>;
fn seek(&self, rate: f64, format: Format, flags: SeekFlags, start_type: SeekType, start: i64, stop_type: SeekType, stop: i64) -> Result<(), glib::error::BoolError>;
fn seek_simple(&self, format: Format, seek_flags: SeekFlags, seek_pos: i64) -> Result<(), glib::error::BoolError>;
fn set_base_time(&self, time: ClockTime);
fn set_bus(&self, bus: &Bus);
@ -236,7 +223,7 @@ impl<O: IsA<Element> + IsA<glib::object::Object>> ElementExt for O {
fn get_base_time(&self) -> ClockTime {
unsafe {
ffi::gst_element_get_base_time(self.to_glib_none().0)
from_glib(ffi::gst_element_get_base_time(self.to_glib_none().0))
}
}
@ -292,7 +279,7 @@ impl<O: IsA<Element> + IsA<glib::object::Object>> ElementExt for O {
fn get_start_time(&self) -> ClockTime {
unsafe {
ffi::gst_element_get_start_time(self.to_glib_none().0)
from_glib(ffi::gst_element_get_start_time(self.to_glib_none().0))
}
}
@ -300,7 +287,7 @@ impl<O: IsA<Element> + IsA<glib::object::Object>> ElementExt for O {
unsafe {
let mut state = mem::uninitialized();
let mut pending = mem::uninitialized();
let ret = from_glib(ffi::gst_element_get_state(self.to_glib_none().0, &mut state, &mut pending, timeout));
let ret = from_glib(ffi::gst_element_get_state(self.to_glib_none().0, &mut state, &mut pending, timeout.to_glib()));
(ret, from_glib(state), from_glib(pending))
}
}
@ -412,30 +399,6 @@ impl<O: IsA<Element> + IsA<glib::object::Object>> ElementExt for O {
}
}
fn query_convert(&self, src_format: Format, src_val: i64, dest_format: Format) -> Option<i64> {
unsafe {
let mut dest_val = mem::uninitialized();
let ret = from_glib(ffi::gst_element_query_convert(self.to_glib_none().0, src_format.to_glib(), src_val, dest_format.to_glib(), &mut dest_val));
if ret { Some(dest_val) } else { None }
}
}
fn query_duration(&self, format: Format) -> Option<i64> {
unsafe {
let mut duration = mem::uninitialized();
let ret = from_glib(ffi::gst_element_query_duration(self.to_glib_none().0, format.to_glib(), &mut duration));
if ret { Some(duration) } else { None }
}
}
fn query_position(&self, format: Format) -> Option<i64> {
unsafe {
let mut cur = mem::uninitialized();
let ret = from_glib(ffi::gst_element_query_position(self.to_glib_none().0, format.to_glib(), &mut cur));
if ret { Some(cur) } else { None }
}
}
fn release_request_pad<P: IsA<Pad>>(&self, pad: &P) {
unsafe {
ffi::gst_element_release_request_pad(self.to_glib_none().0, pad.to_glib_none().0);
@ -458,21 +421,9 @@ impl<O: IsA<Element> + IsA<glib::object::Object>> ElementExt for O {
}
}
fn seek(&self, rate: f64, format: Format, flags: SeekFlags, start_type: SeekType, start: i64, stop_type: SeekType, stop: i64) -> Result<(), glib::error::BoolError> {
unsafe {
glib::error::BoolError::from_glib(ffi::gst_element_seek(self.to_glib_none().0, rate, format.to_glib(), flags.to_glib(), start_type.to_glib(), start, stop_type.to_glib(), stop), "Failed to seek")
}
}
fn seek_simple(&self, format: Format, seek_flags: SeekFlags, seek_pos: i64) -> Result<(), glib::error::BoolError> {
unsafe {
glib::error::BoolError::from_glib(ffi::gst_element_seek_simple(self.to_glib_none().0, format.to_glib(), seek_flags.to_glib(), seek_pos), "Failed to seek")
}
}
fn set_base_time(&self, time: ClockTime) {
unsafe {
ffi::gst_element_set_base_time(self.to_glib_none().0, time);
ffi::gst_element_set_base_time(self.to_glib_none().0, time.to_glib());
}
}
@ -502,7 +453,7 @@ impl<O: IsA<Element> + IsA<glib::object::Object>> ElementExt for O {
fn set_start_time(&self, time: ClockTime) {
unsafe {
ffi::gst_element_set_start_time(self.to_glib_none().0, time);
ffi::gst_element_set_start_time(self.to_glib_none().0, time.to_glib());
}
}

View file

@ -153,7 +153,7 @@ pub fn update_registry() -> Result<(), glib::error::BoolError> {
pub fn util_get_timestamp() -> ClockTime {
assert_initialized_main_thread!();
unsafe {
ffi::gst_util_get_timestamp()
from_glib(ffi::gst_util_get_timestamp())
}
}

View file

@ -152,7 +152,6 @@ pub use self::flags::StreamFlags;
pub use self::flags::StreamType;
mod alias;
pub use self::alias::ClockTime;
pub use self::alias::ClockTimeDiff;
pub use self::alias::ElementFactoryListType;

View file

@ -122,7 +122,7 @@ impl<O: IsA<Object> + IsA<glib::object::Object>> GstObjectExt for O {
fn get_control_rate(&self) -> ClockTime {
unsafe {
ffi::gst_object_get_control_rate(self.to_glib_none().0)
from_glib(ffi::gst_object_get_control_rate(self.to_glib_none().0))
}
}
@ -198,7 +198,7 @@ impl<O: IsA<Object> + IsA<glib::object::Object>> GstObjectExt for O {
fn set_control_rate(&self, control_rate: ClockTime) {
unsafe {
ffi::gst_object_set_control_rate(self.to_glib_none().0, control_rate);
ffi::gst_object_set_control_rate(self.to_glib_none().0, control_rate.to_glib());
}
}
@ -218,13 +218,13 @@ impl<O: IsA<Object> + IsA<glib::object::Object>> GstObjectExt for O {
fn suggest_next_sync(&self) -> ClockTime {
unsafe {
ffi::gst_object_suggest_next_sync(self.to_glib_none().0)
from_glib(ffi::gst_object_suggest_next_sync(self.to_glib_none().0))
}
}
fn sync_values(&self, timestamp: ClockTime) -> Result<(), glib::error::BoolError> {
unsafe {
glib::error::BoolError::from_glib(ffi::gst_object_sync_values(self.to_glib_none().0, timestamp), "Failed to sync values")
glib::error::BoolError::from_glib(ffi::gst_object_sync_values(self.to_glib_none().0, timestamp.to_glib()), "Failed to sync values")
}
}

View file

@ -6,7 +6,6 @@ use Element;
use Event;
use EventType;
use FlowReturn;
use Format;
use Object;
use PadDirection;
use PadLinkCheck;
@ -151,22 +150,10 @@ pub trait PadExt {
fn peer_query_caps<'a, P: Into<Option<&'a Caps>>>(&self, filter: P) -> Option<Caps>;
fn peer_query_convert(&self, src_format: Format, src_val: i64, dest_format: Format) -> Option<i64>;
fn peer_query_duration(&self, format: Format) -> Option<i64>;
fn peer_query_position(&self, format: Format) -> Option<i64>;
fn query_accept_caps(&self, caps: &Caps) -> bool;
fn query_caps<'a, P: Into<Option<&'a Caps>>>(&self, filter: P) -> Option<Caps>;
fn query_convert(&self, src_format: Format, src_val: i64, dest_format: Format) -> Option<i64>;
fn query_duration(&self, format: Format) -> Option<i64>;
fn query_position(&self, format: Format) -> Option<i64>;
//fn set_activate_function_full<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(&self, activate: /*Unknown conversion*//*Unimplemented*/PadActivateFunction, user_data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify);
//fn set_activatemode_function_full<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(&self, activatemode: /*Unknown conversion*//*Unimplemented*/PadActivateModeFunction, user_data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify);
@ -449,30 +436,6 @@ impl<O: IsA<Pad> + IsA<glib::object::Object>> PadExt for O {
}
}
fn peer_query_convert(&self, src_format: Format, src_val: i64, dest_format: Format) -> Option<i64> {
unsafe {
let mut dest_val = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_peer_query_convert(self.to_glib_none().0, src_format.to_glib(), src_val, dest_format.to_glib(), &mut dest_val));
if ret { Some(dest_val) } else { None }
}
}
fn peer_query_duration(&self, format: Format) -> Option<i64> {
unsafe {
let mut duration = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_peer_query_duration(self.to_glib_none().0, format.to_glib(), &mut duration));
if ret { Some(duration) } else { None }
}
}
fn peer_query_position(&self, format: Format) -> Option<i64> {
unsafe {
let mut cur = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_peer_query_position(self.to_glib_none().0, format.to_glib(), &mut cur));
if ret { Some(cur) } else { None }
}
}
fn query_accept_caps(&self, caps: &Caps) -> bool {
unsafe {
from_glib(ffi::gst_pad_query_accept_caps(self.to_glib_none().0, caps.to_glib_none().0))
@ -487,30 +450,6 @@ impl<O: IsA<Pad> + IsA<glib::object::Object>> PadExt for O {
}
}
fn query_convert(&self, src_format: Format, src_val: i64, dest_format: Format) -> Option<i64> {
unsafe {
let mut dest_val = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_query_convert(self.to_glib_none().0, src_format.to_glib(), src_val, dest_format.to_glib(), &mut dest_val));
if ret { Some(dest_val) } else { None }
}
}
fn query_duration(&self, format: Format) -> Option<i64> {
unsafe {
let mut duration = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_query_duration(self.to_glib_none().0, format.to_glib(), &mut duration));
if ret { Some(duration) } else { None }
}
}
fn query_position(&self, format: Format) -> Option<i64> {
unsafe {
let mut cur = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_query_position(self.to_glib_none().0, format.to_glib(), &mut cur));
if ret { Some(cur) } else { None }
}
}
//fn set_activate_function_full<P: Into<Option</*Unimplemented*/Fundamental: Pointer>>>(&self, activate: /*Unknown conversion*//*Unimplemented*/PadActivateFunction, user_data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
// unsafe { TODO: call ffi::gst_pad_set_activate_function_full() }
//}

View file

@ -84,13 +84,13 @@ impl<O: IsA<Pipeline> + IsA<glib::object::Object>> PipelineExt for O {
fn get_delay(&self) -> ClockTime {
unsafe {
ffi::gst_pipeline_get_delay(self.to_glib_none().0)
from_glib(ffi::gst_pipeline_get_delay(self.to_glib_none().0))
}
}
fn get_latency(&self) -> ClockTime {
unsafe {
ffi::gst_pipeline_get_latency(self.to_glib_none().0)
from_glib(ffi::gst_pipeline_get_latency(self.to_glib_none().0))
}
}
@ -108,13 +108,13 @@ impl<O: IsA<Pipeline> + IsA<glib::object::Object>> PipelineExt for O {
fn set_delay(&self, delay: ClockTime) {
unsafe {
ffi::gst_pipeline_set_delay(self.to_glib_none().0, delay);
ffi::gst_pipeline_set_delay(self.to_glib_none().0, delay.to_glib());
}
}
fn set_latency(&self, latency: ClockTime) {
unsafe {
ffi::gst_pipeline_set_latency(self.to_glib_none().0, latency);
ffi::gst_pipeline_set_latency(self.to_glib_none().0, latency.to_glib());
}
}

View file

@ -21,7 +21,7 @@ use ClockTime;
use glib;
use glib_ffi;
use ffi;
use glib::translate::{from_glib, from_glib_full};
use glib::translate::{from_glib, from_glib_full, ToGlib};
pub struct Readable;
pub struct Writable;
@ -317,27 +317,27 @@ impl BufferRef {
}
pub fn get_pts(&self) -> ClockTime {
self.0.pts
from_glib(self.0.pts)
}
pub fn set_pts(&mut self, pts: ClockTime) {
self.0.pts = pts;
self.0.pts = pts.to_glib();
}
pub fn get_dts(&self) -> ClockTime {
self.0.dts
from_glib(self.0.dts)
}
pub fn set_dts(&mut self, dts: ClockTime) {
self.0.dts = dts;
self.0.dts = dts.to_glib();
}
pub fn get_duration(&self) -> ClockTime {
self.0.duration
from_glib(self.0.duration)
}
pub fn set_duration(&mut self, duration: ClockTime) {
self.0.duration = duration;
self.0.duration = duration.to_glib();
}
pub fn get_flags(&self) -> BufferFlags {
@ -474,17 +474,17 @@ mod tests {
{
let buffer = buffer.get_mut().unwrap();
buffer.set_pts(1);
buffer.set_dts(2);
buffer.set_pts(1.into());
buffer.set_dts(2.into());
buffer.set_offset(3);
buffer.set_offset_end(4);
buffer.set_duration(5);
buffer.set_duration(5.into());
}
assert_eq!(buffer.get_pts(), 1);
assert_eq!(buffer.get_dts(), 2);
assert_eq!(buffer.get_pts(), 1.into());
assert_eq!(buffer.get_dts(), 2.into());
assert_eq!(buffer.get_offset(), 3);
assert_eq!(buffer.get_offset_end(), 4);
assert_eq!(buffer.get_duration(), 5);
assert_eq!(buffer.get_duration(), 5.into());
}
#[test]
@ -499,7 +499,7 @@ mod tests {
assert_ne!(buffer.get_mut(), None);
{
let buffer = buffer.get_mut().unwrap();
buffer.set_pts(1);
buffer.set_pts(1.into());
}
let mut buffer2 = buffer.clone();
@ -515,15 +515,15 @@ mod tests {
assert_ne!(buffer2.as_ptr(), buffer.as_ptr());
}
buffer2.set_pts(2);
buffer2.set_pts(2.into());
let mut data = buffer2.map_writable().unwrap();
assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
data.as_mut_slice()[0] = 0;
}
assert_eq!(buffer.get_pts(), 1);
assert_eq!(buffer2.get_pts(), 2);
assert_eq!(buffer.get_pts(), 1.into());
assert_eq!(buffer2.get_pts(), 2.into());
{
let data = buffer.map_readable().unwrap();

View file

@ -34,14 +34,18 @@ glib_wrapper! {
unsafe extern "C" fn trampoline_wait_async(
clock: *mut ffi::GstClock,
time: ClockTime,
time: ffi::GstClockTime,
id: gpointer,
func: gpointer,
) -> gboolean {
let _guard = CallbackGuard::new();
#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
let f: &&(Fn(&Clock, ClockTime, &ClockId) -> bool + Send + 'static) = transmute(func);
f(&from_glib_borrow(clock), time, &from_glib_borrow(id)).to_glib()
f(
&from_glib_borrow(clock),
from_glib(time),
&from_glib_borrow(id),
).to_glib()
}
unsafe extern "C" fn destroy_closure_wait_async(ptr: gpointer) {
@ -60,7 +64,7 @@ fn into_raw_wait_async<F: Fn(&Clock, ClockTime, &ClockId) -> bool + Send + 'stat
impl ClockId {
pub fn get_time(&self) -> ClockTime {
unsafe { ffi::gst_clock_id_get_time(self.to_glib_none().0) }
unsafe { from_glib(ffi::gst_clock_id_get_time(self.to_glib_none().0)) }
}
pub fn unschedule(&self) {
@ -142,8 +146,8 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExtManual for O {
unsafe {
from_glib_full(ffi::gst_clock_new_periodic_id(
self.to_glib_none().0,
start_time,
interval,
start_time.to_glib(),
interval.to_glib(),
))
}
}
@ -159,8 +163,8 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExtManual for O {
let res: bool = from_glib(ffi::gst_clock_periodic_id_reinit(
self.to_glib_none().0,
id.to_glib_none().0,
start_time,
interval,
start_time.to_glib(),
interval.to_glib(),
));
if res {
Ok(())
@ -174,7 +178,7 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExtManual for O {
unsafe {
from_glib_full(ffi::gst_clock_new_single_shot_id(
self.to_glib_none().0,
time,
time.to_glib(),
))
}
}
@ -184,7 +188,7 @@ impl<O: IsA<Clock> + IsA<glib::object::Object>> ClockExtManual for O {
let res: bool = from_glib(ffi::gst_clock_single_shot_id_reinit(
self.to_glib_none().0,
id.to_glib_none().0,
time,
time.to_glib(),
));
if res {
Ok(())
@ -207,7 +211,7 @@ mod tests {
let clock = SystemClock::obtain();
let now = clock.get_time();
let id = clock.new_single_shot_id(now + 20_000_000).unwrap();
let id = clock.new_single_shot_id(now + 20 * ::MSECOND).unwrap();
let (res, _) = id.wait();
assert!(res == ClockReturn::Ok || res == ClockReturn::Early);
@ -221,7 +225,7 @@ mod tests {
let clock = SystemClock::obtain();
let now = clock.get_time();
let id = clock.new_single_shot_id(now + 20_000_000).unwrap();
let id = clock.new_single_shot_id(now + 20 * ::MSECOND).unwrap();
let res = id.wait_async(move |_, _, _| {
sender.send(()).unwrap();

334
gstreamer/src/clock_time.rs Normal file
View file

@ -0,0 +1,334 @@
// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ops;
use ffi;
use glib::translate::*;
use std::{cmp, fmt};
use muldiv::MulDiv;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
pub struct ClockTime(pub Option<u64>);
impl ClockTime {
pub fn hours(&self) -> Option<u64> {
(*self / ::SECOND / 60 / 60).0
}
pub fn minutes(&self) -> Option<u64> {
(*self / ::SECOND / 60).0
}
pub fn seconds(&self) -> Option<u64> {
(*self / ::SECOND).0
}
pub fn nanoseconds(&self) -> Option<u64> {
self.0
}
pub fn from_seconds(seconds: u64) -> ClockTime {
seconds * ::SECOND
}
pub fn new(nanoseconds: u64) -> ClockTime {
ClockTime(Some(nanoseconds))
}
pub fn none() -> ClockTime {
ClockTime(None)
}
}
impl From<u64> for ClockTime {
fn from(v: u64) -> ClockTime {
from_glib(v)
}
}
impl From<Option<u64>> for ClockTime {
fn from(v: Option<u64>) -> ClockTime {
ClockTime(v)
}
}
impl Into<u64> for ClockTime {
fn into(self) -> u64 {
self.to_glib()
}
}
impl Into<Option<u64>> for ClockTime {
fn into(self) -> Option<u64> {
self.0
}
}
impl ops::Deref for ClockTime {
type Target = Option<u64>;
fn deref(&self) -> &Option<u64> {
&self.0
}
}
impl ops::DerefMut for ClockTime {
fn deref_mut(&mut self) -> &mut Option<u64> {
&mut self.0
}
}
impl AsRef<Option<u64>> for ClockTime {
fn as_ref(&self) -> &Option<u64> {
&self.0
}
}
impl AsMut<Option<u64>> for ClockTime {
fn as_mut(&mut self) -> &mut Option<u64> {
&mut self.0
}
}
impl fmt::Display for ClockTime {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let precision = f.precision().unwrap_or(9);
// TODO: Could also check width and pad the hours as needed
let (h, m, s, ns) = match self.0 {
Some(v) => {
let mut s = v / 1_000_000_000;
let mut m = s / 60;
let h = m / 60;
s %= 60;
m %= 60;
let ns = v % 1_000_000_000;
(h, m, s, ns)
}
None => (99, 99, 99, 999_999_999),
};
if precision == 0 {
f.write_fmt(format_args!("{:02}:{:02}:{:02}", h, m, s))
} else {
let mut divisor = 1;
let precision = cmp::max(precision, 9);
for _ in 0..(9 - precision) {
divisor *= 10;
}
f.write_fmt(format_args!(
"{:02}:{:02}:{:02}.{:0width$}",
h,
m,
s,
ns / divisor,
width = precision
))
}
}
}
macro_rules! impl_op_same(
($op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident, $e:expr) => {
impl ops::$op<ClockTime> for ClockTime {
type Output = ClockTime;
fn $op_name(self, other: ClockTime) -> ClockTime {
match (self.0, other.0) {
(Some(a), Some(b)) => ClockTime(Some($e(a, b))),
_ => ClockTime(None),
}
}
}
impl<'a> ops::$op<&'a ClockTime> for ClockTime {
type Output = ClockTime;
fn $op_name(self, other: &'a ClockTime) -> ClockTime {
self.$op_name(*other)
}
}
impl ops::$op_assign<ClockTime> for ClockTime {
fn $op_assign_name(&mut self, other: ClockTime) {
match (self.0, other.0) {
(Some(a), Some(b)) => self.0 = Some($e(a, b)),
_ => self.0 = None,
}
}
}
impl<'a> ops::$op_assign<&'a ClockTime> for ClockTime {
fn $op_assign_name(&mut self, other: &'a ClockTime) {
self.$op_assign_name(*other)
}
}
};
);
impl_op_same!(Add, add, AddAssign, add_assign, |a, b| a + b);
impl_op_same!(Sub, sub, SubAssign, sub_assign, |a, b| a - b);
impl_op_same!(Mul, mul, MulAssign, mul_assign, |a, b| a * b);
impl_op_same!(Div, div, DivAssign, div_assign, |a, b| a / b);
impl_op_same!(Rem, rem, RemAssign, rem_assign, |a, b| a % b);
macro_rules! impl_op_u64(
($op:ident, $op_name:ident, $op_assign:ident, $op_assign_name:ident, $e:expr) => {
impl ops::$op<u64> for ClockTime {
type Output = ClockTime;
fn $op_name(self, other: u64) -> ClockTime {
match self.0 {
Some(a) => ClockTime(Some($e(a, other))),
_ => ClockTime(None),
}
}
}
impl<'a> ops::$op<&'a u64> for ClockTime {
type Output = ClockTime;
fn $op_name(self, other: &'a u64) -> ClockTime {
self.$op_name(*other)
}
}
impl ops::$op_assign<u64> for ClockTime {
fn $op_assign_name(&mut self, other: u64) {
match self.0 {
Some(a) => self.0 = Some($e(a, other)),
_ => self.0 = None,
}
}
}
impl<'a> ops::$op_assign<&'a u64> for ClockTime {
fn $op_assign_name(&mut self, other: &'a u64) {
self.$op_assign_name(*other)
}
}
};
);
impl_op_u64!(Mul, mul, MulAssign, mul_assign, |a, b| a * b);
impl_op_u64!(Div, div, DivAssign, div_assign, |a, b| a / b);
impl_op_u64!(Rem, rem, RemAssign, rem_assign, |a, b| a % b);
impl ops::Mul<ClockTime> for u64 {
type Output = ClockTime;
fn mul(self, other: ClockTime) -> ClockTime {
other.mul(self)
}
}
impl<'a> ops::Mul<&'a ClockTime> for u64 {
type Output = ClockTime;
fn mul(self, other: &'a ClockTime) -> ClockTime {
other.mul(self)
}
}
#[doc(hidden)]
impl ToGlib for ClockTime {
type GlibType = ffi::GstClockTime;
fn to_glib(&self) -> ffi::GstClockTime {
match self.0 {
None => ffi::GST_CLOCK_TIME_NONE,
Some(v) => v,
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstClockTime> for ClockTime {
fn from_glib(value: ffi::GstClockTime) -> Self {
skip_assert_initialized!();
match value {
ffi::GST_CLOCK_TIME_NONE => ClockTime(None),
value => ClockTime(Some(value)),
}
}
}
impl MulDiv<ClockTime> for ClockTime {
type Output = ClockTime;
fn mul_div_floor(self, num: ClockTime, denom: ClockTime) -> Option<Self::Output> {
match (self.0, num.0, denom.0) {
(Some(s), Some(n), Some(d)) => s.mul_div_floor(n, d).map(ClockTime::new),
_ => Some(ClockTime(None)),
}
}
fn mul_div_round(self, num: ClockTime, denom: ClockTime) -> Option<Self::Output> {
match (self.0, num.0, denom.0) {
(Some(s), Some(n), Some(d)) => s.mul_div_round(n, d).map(ClockTime::new),
_ => Some(ClockTime(None)),
}
}
fn mul_div_ceil(self, num: ClockTime, denom: ClockTime) -> Option<Self::Output> {
match (self.0, num.0, denom.0) {
(Some(s), Some(n), Some(d)) => s.mul_div_ceil(n, d).map(ClockTime::new),
_ => Some(ClockTime(None)),
}
}
}
impl<'a> MulDiv<&'a ClockTime> for ClockTime {
type Output = ClockTime;
fn mul_div_floor(self, num: &ClockTime, denom: &ClockTime) -> Option<Self::Output> {
self.mul_div_floor(*num, *denom)
}
fn mul_div_round(self, num: &ClockTime, denom: &ClockTime) -> Option<Self::Output> {
self.mul_div_round(*num, *denom)
}
fn mul_div_ceil(self, num: &ClockTime, denom: &ClockTime) -> Option<Self::Output> {
self.mul_div_ceil(*num, *denom)
}
}
impl<'a> MulDiv<u64> for ClockTime {
type Output = ClockTime;
fn mul_div_floor(self, num: u64, denom: u64) -> Option<Self::Output> {
self.mul_div_floor(ClockTime::from(num), ClockTime::from(denom))
}
fn mul_div_round(self, num: u64, denom: u64) -> Option<Self::Output> {
self.mul_div_round(ClockTime::from(num), ClockTime::from(denom))
}
fn mul_div_ceil(self, num: u64, denom: u64) -> Option<Self::Output> {
self.mul_div_ceil(ClockTime::from(num), ClockTime::from(denom))
}
}
impl<'a> MulDiv<&'a u64> for ClockTime {
type Output = ClockTime;
fn mul_div_floor(self, num: &u64, denom: &u64) -> Option<Self::Output> {
self.mul_div_floor(*num, *denom)
}
fn mul_div_round(self, num: &u64, denom: &u64) -> Option<Self::Output> {
self.mul_div_round(*num, *denom)
}
fn mul_div_ceil(self, num: &u64, denom: &u64) -> Option<Self::Output> {
self.mul_div_ceil(*num, *denom)
}
}

View file

@ -19,6 +19,7 @@ use PadTemplate;
use miniobject::MiniObject;
use std::ffi::CStr;
use std::mem;
use libc;
@ -134,6 +135,29 @@ pub trait ElementExtManual {
#[cfg(any(feature = "v1_10", feature = "dox"))]
fn remove_property_notify_watch(&self, watch_id: NotifyWatchId);
fn query_convert<V: Into<::FormatValue>>(
&self,
src_val: V,
dest_format: ::Format,
) -> Option<::FormatValue>;
fn query_duration(&self, format: ::Format) -> Option<::FormatValue>;
fn query_position(&self, format: ::Format) -> Option<::FormatValue>;
fn seek<V: Into<::FormatValue>>(
&self,
rate: f64,
flags: ::SeekFlags,
start_type: ::SeekType,
start: V,
stop_type: ::SeekType,
stop: V,
) -> Result<(), glib::error::BoolError>;
fn seek_simple<V: Into<::FormatValue>>(
&self,
seek_flags: ::SeekFlags,
seek_pos: V,
) -> Result<(), glib::error::BoolError>;
}
impl<O: IsA<Element>> ElementExtManual for O {
@ -337,6 +361,111 @@ impl<O: IsA<Element>> ElementExtManual for O {
ffi::gst_element_remove_property_notify_watch(self.to_glib_none().0, watch_id.0);
}
}
fn query_convert<V: Into<::FormatValue>>(
&self,
src_val: V,
dest_format: ::Format,
) -> Option<::FormatValue> {
let src_val = src_val.into();
unsafe {
let mut dest_val = mem::uninitialized();
let ret = from_glib(ffi::gst_element_query_convert(
self.to_glib_none().0,
src_val.to_format().to_glib(),
src_val.to_value(),
dest_format.to_glib(),
&mut dest_val,
));
if ret {
Some(::FormatValue::new(dest_format, dest_val))
} else {
None
}
}
}
fn query_duration(&self, format: ::Format) -> Option<::FormatValue> {
unsafe {
let mut duration = mem::uninitialized();
let ret = from_glib(ffi::gst_element_query_duration(
self.to_glib_none().0,
format.to_glib(),
&mut duration,
));
if ret {
Some(::FormatValue::new(format, duration))
} else {
None
}
}
}
fn query_position(&self, format: ::Format) -> Option<::FormatValue> {
unsafe {
let mut cur = mem::uninitialized();
let ret = from_glib(ffi::gst_element_query_position(
self.to_glib_none().0,
format.to_glib(),
&mut cur,
));
if ret {
Some(::FormatValue::new(format, cur))
} else {
None
}
}
}
fn seek<V: Into<::FormatValue>>(
&self,
rate: f64,
flags: ::SeekFlags,
start_type: ::SeekType,
start: V,
stop_type: ::SeekType,
stop: V,
) -> Result<(), glib::error::BoolError> {
let start = start.into();
let stop = stop.into();
assert_eq!(stop.to_format(), start.to_format());
unsafe {
glib::error::BoolError::from_glib(
ffi::gst_element_seek(
self.to_glib_none().0,
rate,
start.to_format().to_glib(),
flags.to_glib(),
start_type.to_glib(),
start.to_value(),
stop_type.to_glib(),
stop.to_value(),
),
"Failed to seek",
)
}
}
fn seek_simple<V: Into<::FormatValue>>(
&self,
seek_flags: ::SeekFlags,
seek_pos: V,
) -> Result<(), glib::error::BoolError> {
let seek_pos = seek_pos.into();
unsafe {
glib::error::BoolError::from_glib(
ffi::gst_element_seek_simple(
self.to_glib_none().0,
seek_pos.to_format().to_glib(),
seek_flags.to_glib(),
seek_pos.to_value(),
),
"Failed to seek",
)
}
}
}
lazy_static!{

View file

@ -151,14 +151,17 @@ impl GstRc<EventRef> {
TagBuilder::new(tags)
}
pub fn new_buffer_size<'a>(
format: ::Format,
minsize: i64,
maxsize: i64,
pub fn new_buffer_size<'a, V: Into<::FormatValue>>(
minsize: V,
maxsize: V,
async: bool,
) -> BufferSizeBuilder<'a> {
assert_initialized_main_thread!();
BufferSizeBuilder::new(format, minsize, maxsize, async)
let minsize = minsize.into();
let maxsize = maxsize.into();
assert_eq!(minsize.to_format(), maxsize.to_format());
BufferSizeBuilder::new(minsize, maxsize, async)
}
pub fn new_sink_message<'a>(name: &'a str, msg: &'a ::Message) -> SinkMessageBuilder<'a> {
@ -191,9 +194,10 @@ impl GstRc<EventRef> {
ProtectionBuilder::new(system_id, data, origin)
}
pub fn new_segment_done<'a>(format: ::Format, position: i64) -> SegmentDoneBuilder<'a> {
pub fn new_segment_done<'a, V: Into<::FormatValue>>(position: V) -> SegmentDoneBuilder<'a> {
assert_initialized_main_thread!();
SegmentDoneBuilder::new(format, position)
let position = position.into();
SegmentDoneBuilder::new(position)
}
pub fn new_gap<'a>(timestamp: u64, duration: u64) -> GapBuilder<'a> {
@ -211,17 +215,20 @@ impl GstRc<EventRef> {
QosBuilder::new(type_, proportion, diff, timestamp)
}
pub fn new_seek<'a>(
pub fn new_seek<'a, V: Into<::FormatValue>>(
rate: f64,
format: ::Format,
flags: ::SeekFlags,
start_type: ::SeekType,
start: i64,
start: V,
stop_type: ::SeekType,
stop: i64,
stop: V,
) -> SeekBuilder<'a> {
assert_initialized_main_thread!();
SeekBuilder::new(rate, format, flags, start_type, start, stop_type, stop)
let start = start.into();
let stop = stop.into();
assert_eq!(start.to_format(), stop.to_format());
SeekBuilder::new(rate, flags, start_type, start, stop_type, stop)
}
pub fn new_navigation<'a>(structure: ::Structure) -> NavigationBuilder<'a> {
@ -436,7 +443,7 @@ impl<'a> Tag<'a> {
pub struct BufferSize<'a>(&'a EventRef);
impl<'a> BufferSize<'a> {
pub fn get(&self) -> (::Format, i64, i64, bool) {
pub fn get(&self) -> (::FormatValue, ::FormatValue, bool) {
unsafe {
let mut fmt = mem::uninitialized();
let mut minsize = mem::uninitialized();
@ -450,7 +457,11 @@ impl<'a> BufferSize<'a> {
&mut maxsize,
&mut async,
);
(from_glib(fmt), minsize, maxsize, from_glib(async))
(
::FormatValue::new(from_glib(fmt), minsize),
::FormatValue::new(from_glib(fmt), maxsize),
from_glib(async),
)
}
}
}
@ -522,14 +533,14 @@ impl<'a> Protection<'a> {
pub struct SegmentDone<'a>(&'a EventRef);
impl<'a> SegmentDone<'a> {
pub fn get(&self) -> (::Format, i64) {
pub fn get(&self) -> ::FormatValue {
unsafe {
let mut fmt = mem::uninitialized();
let mut position = mem::uninitialized();
ffi::gst_event_parse_segment_done(self.0.as_mut_ptr(), &mut fmt, &mut position);
(from_glib(fmt), position)
::FormatValue::new(from_glib(fmt), position)
}
}
}
@ -573,7 +584,16 @@ impl<'a> Qos<'a> {
pub struct Seek<'a>(&'a EventRef);
impl<'a> Seek<'a> {
pub fn get(&self) -> (f64, ::Format, ::SeekFlags, ::SeekType, i64, ::SeekType, i64) {
pub fn get(
&self,
) -> (
f64,
::SeekFlags,
::SeekType,
::FormatValue,
::SeekType,
::FormatValue,
) {
unsafe {
let mut rate = mem::uninitialized();
let mut fmt = mem::uninitialized();
@ -596,12 +616,11 @@ impl<'a> Seek<'a> {
(
rate,
from_glib(fmt),
from_glib(flags),
from_glib(start_type),
start,
::FormatValue::new(from_glib(fmt), start),
from_glib(stop_type),
stop,
::FormatValue::new(from_glib(fmt), stop),
)
}
}
@ -921,19 +940,17 @@ pub struct BufferSizeBuilder<'a> {
seqnum: Option<u32>,
running_time_offset: Option<i64>,
other_fields: Vec<(&'a str, &'a ToValue)>,
fmt: ::Format,
minsize: i64,
maxsize: i64,
minsize: ::FormatValue,
maxsize: ::FormatValue,
async: bool,
}
impl<'a> BufferSizeBuilder<'a> {
fn new(fmt: ::Format, minsize: i64, maxsize: i64, async: bool) -> Self {
fn new(minsize: ::FormatValue, maxsize: ::FormatValue, async: bool) -> Self {
skip_assert_initialized!();
Self {
seqnum: None,
running_time_offset: None,
other_fields: Vec::new(),
fmt: fmt,
minsize: minsize,
maxsize: maxsize,
async: async,
@ -941,7 +958,12 @@ impl<'a> BufferSizeBuilder<'a> {
}
event_builder_generic_impl!(|s: &Self| {
ffi::gst_event_new_buffer_size(s.fmt.to_glib(), s.minsize, s.maxsize, s.async.to_glib())
ffi::gst_event_new_buffer_size(
s.minsize.to_format().to_glib(),
s.minsize.to_value(),
s.maxsize.to_value(),
s.async.to_glib(),
)
});
}
@ -1067,23 +1089,21 @@ pub struct SegmentDoneBuilder<'a> {
seqnum: Option<u32>,
running_time_offset: Option<i64>,
other_fields: Vec<(&'a str, &'a ToValue)>,
fmt: ::Format,
position: i64,
position: ::FormatValue,
}
impl<'a> SegmentDoneBuilder<'a> {
fn new(fmt: ::Format, position: i64) -> Self {
fn new(position: ::FormatValue) -> Self {
skip_assert_initialized!();
Self {
seqnum: None,
running_time_offset: None,
other_fields: Vec::new(),
fmt: fmt,
position: position,
}
}
event_builder_generic_impl!(|s: &Self| {
ffi::gst_event_new_segment_done(s.fmt.to_glib(), s.position)
ffi::gst_event_new_segment_done(s.position.to_format().to_glib(), s.position.to_value())
});
}
@ -1142,22 +1162,20 @@ pub struct SeekBuilder<'a> {
running_time_offset: Option<i64>,
other_fields: Vec<(&'a str, &'a ToValue)>,
rate: f64,
fmt: ::Format,
flags: ::SeekFlags,
start_type: ::SeekType,
start: i64,
start: ::FormatValue,
stop_type: ::SeekType,
stop: i64,
stop: ::FormatValue,
}
impl<'a> SeekBuilder<'a> {
fn new(
rate: f64,
fmt: ::Format,
flags: ::SeekFlags,
start_type: ::SeekType,
start: i64,
start: ::FormatValue,
stop_type: ::SeekType,
stop: i64,
stop: ::FormatValue,
) -> Self {
skip_assert_initialized!();
Self {
@ -1165,7 +1183,6 @@ impl<'a> SeekBuilder<'a> {
running_time_offset: None,
other_fields: Vec::new(),
rate: rate,
fmt: fmt,
flags: flags,
start_type,
start,
@ -1177,12 +1194,12 @@ impl<'a> SeekBuilder<'a> {
event_builder_generic_impl!(|s: &Self| {
ffi::gst_event_new_seek(
s.rate,
s.fmt.to_glib(),
s.start.to_format().to_glib(),
s.flags.to_glib(),
s.start_type.to_glib(),
s.start,
s.start.to_value(),
s.stop_type.to_glib(),
s.stop,
s.stop.to_value(),
)
});
}

169
gstreamer/src/format.rs Normal file
View file

@ -0,0 +1,169 @@
// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ClockTime;
use Format;
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum FormatValue {
Undefined(i64),
Default(Option<u64>),
Bytes(Option<u64>),
Time(ClockTime),
Buffers(Option<u64>),
Percent(Option<u32>),
Other(Format, i64),
}
impl FormatValue {
pub fn new(format: Format, value: i64) -> Self {
match format {
Format::Undefined => FormatValue::Undefined(value),
Format::Default => FormatValue::Default(if value == -1 {
None
} else {
Some(value as u64)
}),
Format::Bytes => FormatValue::Bytes(if value == -1 {
None
} else {
Some(value as u64)
}),
Format::Time => FormatValue::Time(if value == -1 {
ClockTime::none()
} else {
ClockTime::from(value as u64)
}),
Format::Buffers => FormatValue::Buffers(if value == -1 {
None
} else {
Some(value as u64)
}),
Format::Percent => FormatValue::Percent(if value == -1 {
None
} else {
Some(value as u32)
}),
Format::__Unknown(_) => FormatValue::Other(format, value),
}
}
pub fn from_undefined(v: i64) -> Self {
FormatValue::Undefined(v)
}
pub fn from_default<V: Into<Option<u64>>>(v: V) -> Self {
FormatValue::Default(v.into())
}
pub fn from_bytes<V: Into<Option<u64>>>(v: V) -> Self {
FormatValue::Bytes(v.into())
}
pub fn from_time(v: ClockTime) -> Self {
FormatValue::Time(v)
}
pub fn from_buffers<V: Into<Option<u64>>>(v: V) -> Self {
FormatValue::Buffers(v.into())
}
pub fn from_percent<V: Into<Option<u32>>>(v: V) -> Self {
FormatValue::Percent(v.into())
}
pub fn from_other(format: Format, v: i64) -> Self {
FormatValue::Other(format, v)
}
pub fn to_format(&self) -> Format {
match *self {
FormatValue::Undefined(_) => Format::Undefined,
FormatValue::Default(_) => Format::Default,
FormatValue::Bytes(_) => Format::Bytes,
FormatValue::Time(_) => Format::Time,
FormatValue::Buffers(_) => Format::Buffers,
FormatValue::Percent(_) => Format::Percent,
FormatValue::Other(f, _) => f,
}
}
pub fn to_value(&self) -> i64 {
match *self {
FormatValue::Undefined(v) => v,
FormatValue::Default(v) => v.map(|v| v as i64).unwrap_or(-1),
FormatValue::Bytes(v) => v.map(|v| v as i64).unwrap_or(-1),
FormatValue::Time(v) => v.map(|v| v as i64).unwrap_or(-1),
FormatValue::Buffers(v) => v.map(|v| v as i64).unwrap_or(-1),
FormatValue::Percent(v) => v.map(|v| v as i64).unwrap_or(-1),
FormatValue::Other(_, v) => v,
}
}
pub fn try_to_undefined(&self) -> Option<i64> {
if let FormatValue::Undefined(v) = *self {
Some(v)
} else {
None
}
}
pub fn try_to_default(&self) -> Option<Option<u64>> {
if let FormatValue::Default(v) = *self {
Some(v)
} else {
None
}
}
pub fn try_to_bytes(&self) -> Option<Option<u64>> {
if let FormatValue::Bytes(v) = *self {
Some(v)
} else {
None
}
}
pub fn try_to_time(&self) -> Option<ClockTime> {
if let FormatValue::Time(v) = *self {
Some(v)
} else {
None
}
}
pub fn try_to_buffers(&self) -> Option<Option<u64>> {
if let FormatValue::Buffers(v) = *self {
Some(v)
} else {
None
}
}
pub fn try_to_percent(&self) -> Option<Option<u32>> {
if let FormatValue::Percent(v) = *self {
Some(v)
} else {
None
}
}
pub fn try_to_other(&self) -> Option<(Format, i64)> {
if let FormatValue::Other(f, v) = *self {
Some((f, v))
} else {
None
}
}
}
impl From<ClockTime> for FormatValue {
fn from(v: ClockTime) -> FormatValue {
FormatValue::Time(v)
}
}

View file

@ -25,6 +25,8 @@ extern crate num_rational;
#[cfg(feature = "futures")]
extern crate futures;
extern crate muldiv;
use glib::translate::{from_glib, from_glib_full};
macro_rules! callback_guard {
@ -102,6 +104,8 @@ mod iterator;
mod device_provider;
mod parse_context;
mod enums;
mod clock_time;
mod format;
pub use object::GstObjectExtManual;
pub use element::{ElementExtManual, ElementMessageType, NotifyWatchId};
pub use element::{ELEMENT_METADATA_AUTHOR, ELEMENT_METADATA_DESCRIPTION, ELEMENT_METADATA_DOC_URI,
@ -117,6 +121,8 @@ pub use parse_context::ParseContext;
#[cfg(feature = "futures")]
pub use bus::BusStream;
pub use enums::{StateChangeSuccess, StateChangeError};
pub use clock_time::ClockTime;
pub use format::FormatValue;
mod value;
pub use value::*;
@ -151,12 +157,15 @@ pub fn init() -> Result<(), glib::Error> {
}
pub const BUFFER_OFFSET_NONE: u64 = ffi::GST_BUFFER_OFFSET_NONE;
pub const CLOCK_TIME_NONE: ClockTime = ffi::GST_CLOCK_TIME_NONE;
pub const CLOCK_TIME_NONE: ClockTime = ClockTime(None);
pub const SECOND: ClockTime = 1_000_000_000;
pub const MSECOND: ClockTime = 1_000_000;
pub const USECOND: ClockTime = 1_000;
pub const NSECOND: ClockTime = 1;
pub const SECOND: ClockTime = ClockTime(Some(1_000_000_000));
pub const MSECOND: ClockTime = ClockTime(Some(1_000_000));
pub const USECOND: ClockTime = ClockTime(Some(1_000));
pub const NSECOND: ClockTime = ClockTime(Some(1));
pub const FORMAT_PERCENT_MAX: u32 = ffi::GST_FORMAT_PERCENT_MAX as u32;
pub const FORMAT_PERCENT_SCALE: u32 = ffi::GST_FORMAT_PERCENT_SCALE as u32;
// Re-export all the traits in a prelude module, so that applications
// can always "use gst::prelude::*" without getting conflicts
@ -178,6 +187,8 @@ pub mod prelude {
pub use tags::Tag;
pub use miniobject::MiniObject;
pub use muldiv::MulDiv;
}
mod utils;

View file

@ -200,14 +200,16 @@ impl GstRc<MessageRef> {
ElementBuilder::new(structure)
}
pub fn new_segment_start<'a>(format: ::Format, position: i64) -> SegmentStartBuilder<'a> {
pub fn new_segment_start<'a, V: Into<::FormatValue>>(position: V) -> SegmentStartBuilder<'a> {
assert_initialized_main_thread!();
SegmentStartBuilder::new(format, position)
let position = position.into();
SegmentStartBuilder::new(position)
}
pub fn new_segment_done<'a>(format: ::Format, position: i64) -> SegmentDoneBuilder<'a> {
pub fn new_segment_done<'a, V: Into<::FormatValue>>(position: V) -> SegmentDoneBuilder<'a> {
assert_initialized_main_thread!();
SegmentDoneBuilder::new(format, position)
let position = position.into();
SegmentDoneBuilder::new(position)
}
pub fn new_duration_changed<'a>() -> DurationChangedBuilder<'a> {
@ -723,28 +725,28 @@ pub struct Element<'a>(&'a MessageRef);
pub struct SegmentStart<'a>(&'a MessageRef);
impl<'a> SegmentStart<'a> {
pub fn get(&self) -> (::Format, i64) {
pub fn get(&self) -> ::FormatValue {
unsafe {
let mut format = mem::uninitialized();
let mut position = mem::uninitialized();
ffi::gst_message_parse_segment_start(self.0.as_mut_ptr(), &mut format, &mut position);
(from_glib(format), position)
::FormatValue::new(from_glib(format), position)
}
}
}
pub struct SegmentDone<'a>(&'a MessageRef);
impl<'a> SegmentDone<'a> {
pub fn get(&self) -> (::Format, i64) {
pub fn get(&self) -> ::FormatValue {
unsafe {
let mut format = mem::uninitialized();
let mut position = mem::uninitialized();
ffi::gst_message_parse_segment_done(self.0.as_mut_ptr(), &mut format, &mut position);
(from_glib(format), position)
::FormatValue::new(from_glib(format), position)
}
}
}
@ -1749,23 +1751,25 @@ pub struct SegmentStartBuilder<'a> {
src: Option<Object>,
seqnum: Option<u32>,
other_fields: Vec<(&'a str, &'a ToValue)>,
format: ::Format,
position: i64,
position: ::FormatValue,
}
impl<'a> SegmentStartBuilder<'a> {
fn new(format: ::Format, position: i64) -> Self {
fn new(position: ::FormatValue) -> Self {
skip_assert_initialized!();
Self {
src: None,
seqnum: None,
other_fields: Vec::new(),
format: format,
position: position,
}
}
message_builder_generic_impl!(|s: &mut Self, src| {
ffi::gst_message_new_segment_start(src, s.format.to_glib(), s.position)
ffi::gst_message_new_segment_start(
src,
s.position.to_format().to_glib(),
s.position.to_value(),
)
});
}
@ -1773,23 +1777,25 @@ pub struct SegmentDoneBuilder<'a> {
src: Option<Object>,
seqnum: Option<u32>,
other_fields: Vec<(&'a str, &'a ToValue)>,
format: ::Format,
position: i64,
position: ::FormatValue,
}
impl<'a> SegmentDoneBuilder<'a> {
fn new(format: ::Format, position: i64) -> Self {
fn new(position: ::FormatValue) -> Self {
skip_assert_initialized!();
Self {
src: None,
seqnum: None,
other_fields: Vec::new(),
format: format,
position: position,
}
}
message_builder_generic_impl!(|s: &mut Self, src| {
ffi::gst_message_new_segment_done(src, s.format.to_glib(), s.position)
ffi::gst_message_new_segment_done(
src,
s.position.to_format().to_glib(),
s.position.to_value(),
)
});
}

View file

@ -11,6 +11,7 @@ use PadProbeType;
use PadProbeReturn;
use Buffer;
use BufferList;
use Format;
use FlowReturn;
use Query;
use QueryRef;
@ -183,6 +184,21 @@ pub trait PadExtManual {
F: Fn(&Pad, &Option<::Object>) + Send + Sync + 'static;
fn start_task<F: FnMut() + Send + 'static>(&self, func: F) -> Result<(), glib::BoolError>;
fn peer_query_convert<V: Into<::FormatValue>>(
&self,
src_val: V,
dest_format: Format,
) -> Option<::FormatValue>;
fn peer_query_duration(&self, format: Format) -> Option<::FormatValue>;
fn peer_query_position(&self, format: Format) -> Option<::FormatValue>;
fn query_convert<V: Into<::FormatValue>>(
&self,
src_val: V,
dest_format: Format,
) -> Option<::FormatValue>;
fn query_duration(&self, format: Format) -> Option<::FormatValue>;
fn query_position(&self, format: Format) -> Option<::FormatValue>;
}
impl<O: IsA<Pad>> PadExtManual for O {
@ -593,6 +609,117 @@ impl<O: IsA<Pad>> PadExtManual for O {
)
}
}
fn peer_query_convert<V: Into<::FormatValue>>(
&self,
src_val: V,
dest_format: Format,
) -> Option<::FormatValue> {
let src_val = src_val.into();
unsafe {
let mut dest_val = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_peer_query_convert(
self.to_glib_none().0,
src_val.to_format().to_glib(),
src_val.to_value(),
dest_format.to_glib(),
&mut dest_val,
));
if ret {
Some(::FormatValue::new(dest_format, dest_val))
} else {
None
}
}
}
fn peer_query_duration(&self, format: Format) -> Option<::FormatValue> {
unsafe {
let mut duration = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_peer_query_duration(
self.to_glib_none().0,
format.to_glib(),
&mut duration,
));
if ret {
Some(::FormatValue::new(format, duration))
} else {
None
}
}
}
fn peer_query_position(&self, format: Format) -> Option<::FormatValue> {
unsafe {
let mut cur = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_peer_query_position(
self.to_glib_none().0,
format.to_glib(),
&mut cur,
));
if ret {
Some(::FormatValue::new(format, cur))
} else {
None
}
}
}
fn query_convert<V: Into<::FormatValue>>(
&self,
src_val: V,
dest_format: Format,
) -> Option<::FormatValue> {
let src_val = src_val.into();
unsafe {
let mut dest_val = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_query_convert(
self.to_glib_none().0,
src_val.to_format().to_glib(),
src_val.to_value(),
dest_format.to_glib(),
&mut dest_val,
));
if ret {
Some(::FormatValue::new(dest_format, dest_val))
} else {
None
}
}
}
fn query_duration(&self, format: Format) -> Option<::FormatValue> {
unsafe {
let mut duration = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_query_duration(
self.to_glib_none().0,
format.to_glib(),
&mut duration,
));
if ret {
Some(::FormatValue::new(format, duration))
} else {
None
}
}
}
fn query_position(&self, format: Format) -> Option<::FormatValue> {
unsafe {
let mut cur = mem::uninitialized();
let ret = from_glib(ffi::gst_pad_query_position(
self.to_glib_none().0,
format.to_glib(),
&mut cur,
));
if ret {
Some(::FormatValue::new(format, cur))
} else {
None
}
}
}
}
unsafe extern "C" fn trampoline_pad_probe(

View file

@ -56,12 +56,12 @@ impl GstRc<QueryRef> {
unsafe { from_glib_full(ffi::gst_query_new_segment(fmt.to_glib())) }
}
pub fn new_convert(src_fmt: ::Format, value: i64, dest_fmt: ::Format) -> Self {
pub fn new_convert(value: ::FormatValue, dest_fmt: ::Format) -> Self {
assert_initialized_main_thread!();
unsafe {
from_glib_full(ffi::gst_query_new_convert(
src_fmt.to_glib(),
value,
value.to_format().to_glib(),
value.to_value(),
dest_fmt.to_glib(),
))
}
@ -207,14 +207,14 @@ pub enum QueryView<T> {
pub struct Position<T>(T);
impl<'a> Position<&'a QueryRef> {
pub fn get(&self) -> (::Format, i64) {
pub fn get(&self) -> ::FormatValue {
unsafe {
let mut fmt = mem::uninitialized();
let mut pos = mem::uninitialized();
ffi::gst_query_parse_position(self.0.as_mut_ptr(), &mut fmt, &mut pos);
(from_glib(fmt), pos)
::FormatValue::new(from_glib(fmt), pos)
}
}
@ -224,9 +224,14 @@ impl<'a> Position<&'a QueryRef> {
}
impl<'a> Position<&'a mut QueryRef> {
pub fn set(&mut self, fmt: ::Format, pos: i64) {
pub fn set<V: Into<::FormatValue>>(&mut self, pos: V) {
let pos = pos.into();
unsafe {
ffi::gst_query_set_position(self.0.as_mut_ptr(), fmt.to_glib(), pos);
ffi::gst_query_set_position(
self.0.as_mut_ptr(),
pos.to_format().to_glib(),
pos.to_value(),
);
}
}
@ -237,14 +242,14 @@ impl<'a> Position<&'a mut QueryRef> {
pub struct Duration<T>(T);
impl<'a> Duration<&'a QueryRef> {
pub fn get(&self) -> (::Format, i64) {
pub fn get(&self) -> ::FormatValue {
unsafe {
let mut fmt = mem::uninitialized();
let mut pos = mem::uninitialized();
ffi::gst_query_parse_duration(self.0.as_mut_ptr(), &mut fmt, &mut pos);
(from_glib(fmt), pos)
::FormatValue::new(from_glib(fmt), pos)
}
}
@ -254,9 +259,14 @@ impl<'a> Duration<&'a QueryRef> {
}
impl<'a> Duration<&'a mut QueryRef> {
pub fn set(&mut self, fmt: ::Format, pos: i64) {
pub fn set<V: Into<::FormatValue>>(&mut self, dur: V) {
let dur = dur.into();
unsafe {
ffi::gst_query_set_duration(self.0.as_mut_ptr(), fmt.to_glib(), pos);
ffi::gst_query_set_duration(
self.0.as_mut_ptr(),
dur.to_format().to_glib(),
dur.to_value(),
);
}
}
@ -324,7 +334,7 @@ impl<'a> Rate<&'a mut QueryRef> {
pub struct Seeking<T>(T);
impl<'a> Seeking<&'a QueryRef> {
pub fn get(&self) -> (::Format, bool, i64, i64) {
pub fn get(&self) -> (bool, ::FormatValue, ::FormatValue) {
unsafe {
let mut fmt = mem::uninitialized();
let mut seekable = mem::uninitialized();
@ -338,7 +348,11 @@ impl<'a> Seeking<&'a QueryRef> {
&mut end,
);
(from_glib(fmt), from_glib(seekable), start, end)
(
from_glib(seekable),
::FormatValue::new(from_glib(fmt), start),
::FormatValue::new(from_glib(fmt), end),
)
}
}
@ -348,14 +362,19 @@ impl<'a> Seeking<&'a QueryRef> {
}
impl<'a> Seeking<&'a mut QueryRef> {
pub fn set(&mut self, fmt: ::Format, seekable: bool, start: i64, end: i64) {
pub fn set<V: Into<::FormatValue>>(&mut self, seekable: bool, start: V, end: V) {
let start = start.into();
let end = end.into();
assert_eq!(start.to_format(), end.to_format());
unsafe {
ffi::gst_query_set_seeking(
self.0.as_mut_ptr(),
fmt.to_glib(),
start.to_format().to_glib(),
seekable.to_glib(),
start,
end,
start.to_value(),
end.to_value(),
);
}
}
@ -367,7 +386,7 @@ impl<'a> Seeking<&'a mut QueryRef> {
pub struct Segment<T>(T);
impl<'a> Segment<&'a QueryRef> {
pub fn get(&self) -> (f64, ::Format, i64, i64) {
pub fn get(&self) -> (f64, ::FormatValue, ::FormatValue) {
unsafe {
let mut rate = mem::uninitialized();
let mut fmt = mem::uninitialized();
@ -381,7 +400,11 @@ impl<'a> Segment<&'a QueryRef> {
&mut start,
&mut stop,
);
(rate, from_glib(fmt), start, stop)
(
rate,
::FormatValue::new(from_glib(fmt), start),
::FormatValue::new(from_glib(fmt), stop),
)
}
}
@ -391,9 +414,20 @@ impl<'a> Segment<&'a QueryRef> {
}
impl<'a> Segment<&'a mut QueryRef> {
pub fn set(&mut self, rate: f64, fmt: ::Format, start: i64, stop: i64) {
pub fn set<V: Into<::FormatValue>>(&mut self, rate: f64, start: V, stop: V) {
let start = start.into();
let stop = stop.into();
assert_eq!(start.to_format(), stop.to_format());
unsafe {
ffi::gst_query_set_segment(self.0.as_mut_ptr(), rate, fmt.to_glib(), start, stop);
ffi::gst_query_set_segment(
self.0.as_mut_ptr(),
rate,
start.to_format().to_glib(),
start.to_value(),
stop.to_value(),
);
}
}
@ -404,7 +438,7 @@ impl<'a> Segment<&'a mut QueryRef> {
pub struct Convert<T>(T);
impl<'a> Convert<&'a QueryRef> {
pub fn get(&self) -> (::Format, i64, ::Format, i64) {
pub fn get(&self) -> (::FormatValue, ::FormatValue) {
unsafe {
let mut src_fmt = mem::uninitialized();
let mut src = mem::uninitialized();
@ -418,7 +452,10 @@ impl<'a> Convert<&'a QueryRef> {
&mut dest_fmt,
&mut dest,
);
(from_glib(src_fmt), src, from_glib(dest_fmt), dest)
(
::FormatValue::new(from_glib(src_fmt), src),
::FormatValue::new(from_glib(dest_fmt), dest),
)
}
}
@ -428,14 +465,17 @@ impl<'a> Convert<&'a QueryRef> {
}
impl<'a> Convert<&'a mut QueryRef> {
pub fn set(&mut self, src_fmt: ::Format, src: i64, dest_fmt: ::Format, dest: i64) {
pub fn set<V: Into<::FormatValue>>(&mut self, src: V, dest: V) {
let src = src.into();
let dest = dest.into();
unsafe {
ffi::gst_query_set_convert(
self.0.as_mut_ptr(),
src_fmt.to_glib(),
src,
dest_fmt.to_glib(),
dest,
src.to_format().to_glib(),
src.to_value(),
dest.to_format().to_glib(),
dest.to_value(),
);
}
}
@ -494,7 +534,7 @@ impl<'a> Buffering<&'a QueryRef> {
}
}
pub fn get_range(&self) -> (::Format, i64, i64, i64) {
pub fn get_range(&self) -> (::FormatValue, ::FormatValue, i64) {
unsafe {
let mut fmt = mem::uninitialized();
let mut start = mem::uninitialized();
@ -508,7 +548,11 @@ impl<'a> Buffering<&'a QueryRef> {
&mut stop,
&mut estimated_total,
);
(from_glib(fmt), start, stop, estimated_total)
(
::FormatValue::new(from_glib(fmt), start),
::FormatValue::new(from_glib(fmt), stop),
estimated_total,
)
}
}
@ -531,8 +575,18 @@ impl<'a> Buffering<&'a QueryRef> {
}
}
pub fn get_ranges(&self) -> Vec<(i64, i64)> {
pub fn get_ranges(&self) -> Vec<(::FormatValue, ::FormatValue)> {
unsafe {
let mut fmt = mem::uninitialized();
ffi::gst_query_parse_buffering_range(
self.0.as_mut_ptr(),
&mut fmt,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
);
let fmt = from_glib(fmt);
let n = ffi::gst_query_get_n_buffering_ranges(self.0.as_mut_ptr());
let mut res = Vec::with_capacity(n as usize);
for i in 0..n {
@ -545,7 +599,10 @@ impl<'a> Buffering<&'a QueryRef> {
&mut stop,
));
if s {
res.push((start, stop));
res.push((
::FormatValue::new(fmt, start),
::FormatValue::new(fmt, stop),
));
}
}
@ -565,13 +622,18 @@ impl<'a> Buffering<&'a mut QueryRef> {
}
}
pub fn set_range(&mut self, fmt: ::Format, start: i64, stop: i64, estimated_total: i64) {
pub fn set_range<V: Into<::FormatValue>>(&mut self, start: V, stop: V, estimated_total: i64) {
let start = start.into();
let stop = stop.into();
assert_eq!(start.to_format(), stop.to_format());
unsafe {
ffi::gst_query_set_buffering_range(
self.0.as_mut_ptr(),
fmt.to_glib(),
start,
stop,
start.to_format().to_glib(),
start.to_value(),
stop.to_value(),
estimated_total,
);
}
@ -596,10 +658,28 @@ impl<'a> Buffering<&'a mut QueryRef> {
}
}
pub fn add_buffering_ranges(&mut self, ranges: &[(i64, i64)]) {
pub fn add_buffering_ranges<V: Into<::FormatValue> + Copy>(&mut self, ranges: &[(V, V)]) {
unsafe {
let mut fmt = mem::uninitialized();
ffi::gst_query_parse_buffering_range(
self.0.as_mut_ptr(),
&mut fmt,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
);
let fmt = from_glib(fmt);
for &(start, stop) in ranges {
ffi::gst_query_add_buffering_range(self.0.as_mut_ptr(), start, stop);
let start = start.into();
let stop = stop.into();
assert_eq!(start.to_format(), fmt);
assert_eq!(stop.to_format(), fmt);
ffi::gst_query_add_buffering_range(
self.0.as_mut_ptr(),
start.to_value(),
stop.to_value(),
);
}
}
}
@ -955,28 +1035,25 @@ mod tests {
match q.view() {
QueryView::Position(ref p) => {
let (fmt, pos) = p.get();
assert_eq!(fmt, ::Format::Time);
assert_eq!(pos, -1);
let pos = p.get();
assert_eq!(pos.try_to_time(), Some(::CLOCK_TIME_NONE));
}
_ => (),
}
match q.get_mut().unwrap().view_mut() {
QueryView::Position(ref mut p) => {
let (fmt, pos) = p.get();
assert_eq!(fmt, ::Format::Time);
assert_eq!(pos, -1);
p.set(::Format::Time, 2);
let pos = p.get();
assert_eq!(pos.try_to_time(), Some(::CLOCK_TIME_NONE));
p.set(2 * ::SECOND);
}
_ => (),
}
match q.view() {
QueryView::Position(ref p) => {
let (fmt, pos) = p.get();
assert_eq!(fmt, ::Format::Time);
assert_eq!(pos, 2);
let pos = p.get();
assert_eq!(pos.try_to_time(), Some(2 * ::SECOND));
}
_ => (),
}

View file

@ -55,16 +55,16 @@ fn main() {
let position = custom_data
.playbin
.query_position(gst::Format::Time)
.and_then(|v| v.try_to_time())
.expect("Could not query current position.");
let position = position as gst::ClockTime;
// If we didn't know it yet, query the stream duration
if custom_data.duration == gst::CLOCK_TIME_NONE {
custom_data.duration = custom_data
.playbin
.query_duration(gst::Format::Time)
.and_then(|v| v.try_to_time())
.expect("Could not query current duration.")
as gst::ClockTime;
}
// Print current position and total duration
@ -78,9 +78,8 @@ fn main() {
custom_data
.playbin
.seek_simple(
gst::Format::Time,
gst::SeekFlags::FLUSH | gst::SeekFlags::KEY_UNIT,
(30 * gst::SECOND) as i64,
30 * gst::SECOND,
)
.expect("Failed to seek.");
custom_data.seek_done = true;
@ -130,10 +129,10 @@ fn handle_message(custom_data: &mut CustomData, msg: &gst::GstRc<gst::MessageRef
if custom_data.playbin.query(query.get_mut().unwrap()) {
match query.view() {
gst::QueryView::Seeking(seek) => {
let (_fmt, seekable, start, end) = seek.get();
let (seekable, start, end) = seek.get();
custom_data.seek_enabled = seekable;
if seekable {
println!("Seeking is ENABLED from {} to {}", start, end)
println!("Seeking is ENABLED from {:?} to {:?}", start, end)
} else {
println!("Seeking is DISABLED for this stream.")
}

View file

@ -132,9 +132,8 @@ mod tutorial5 {
let pipeline = &pipeline;
let value = slider.get_value() as u64;
if let Err(_) = pipeline.seek_simple(
gst::Format::Time,
gst::SeekFlags::FLUSH | gst::SeekFlags::KEY_UNIT,
((value * gst::SECOND) as i64),
value * gst::SECOND,
) {
eprintln!("Seeking to {} failed", value);
}
@ -148,16 +147,15 @@ mod tutorial5 {
let pipeline = &pipeline;
let lslider = &lslider;
if let Some(dur) = pipeline.query_duration(gst::Format::Time) {
let seconds = (dur as u64) / gst::SECOND;
lslider.set_range(0.0, seconds as f64);
if let Some(gst::FormatValue::Time(dur)) = pipeline.query_duration(gst::Format::Time) {
let seconds = dur / gst::SECOND;
lslider.set_range(0.0, seconds.map(|v| v as f64).unwrap_or(0.0));
}
let position = pipeline.query_position(gst::Format::Time);
if let Some(position) = position {
let seconds = (position as u64) / gst::SECOND;
if let Some(gst::FormatValue::Time(pos)) = pipeline.query_position(gst::Format::Time) {
let seconds = pos / gst::SECOND;
lslider.block_signal(&slider_update_signal_id);
lslider.set_value(seconds as f64);
lslider.set_value(seconds.map(|v| v as f64).unwrap_or(0.0));
lslider.unblock_signal(&slider_update_signal_id);
}