Commit a753c65d authored by Sebastian Dröge's avatar Sebastian Dröge 🍵

video: Add VideoTimeCode bindings

There's a VideoTimeCode type that represents any kind of timecodes,
including invalid ones, and which allows to change each field
individually. And ValidVideoTimeCode that has all fields
validated and that can be used with most of the API.

In C, validation of the timecodes is left to the user and most functions
assert on getting passed valid timecodes.
parent 02dc888a
......@@ -34,9 +34,11 @@ generate = [
"GstVideo.VideoMultiviewFramePacking",
"GstVideo.VideoFilter",
"GstVideo.VideoOverlayFormatFlags",
"GstVideo.VideoTimeCodeFlags",
]
manual = [
"GLib.DateTime",
"GObject.Object",
"Gst.Object",
"Gst.Element",
......@@ -46,6 +48,8 @@ manual = [
"GstVideo.VideoColorimetry",
"GstVideo.VideoColorRange",
"GstVideo.VideoFrame",
"GstVideo.VideoTimeCode",
"GstVideo.VideoTimeCodeInterval",
]
[[object]]
......
......@@ -303,3 +303,31 @@ impl FromGlib<ffi::GstVideoOverlayFormatFlags> for VideoOverlayFormatFlags {
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
bitflags! {
pub struct VideoTimeCodeFlags: u32 {
const NONE = 0;
const DROP_FRAME = 1;
const INTERLACED = 2;
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
#[doc(hidden)]
impl ToGlib for VideoTimeCodeFlags {
type GlibType = ffi::GstVideoTimeCodeFlags;
fn to_glib(&self) -> ffi::GstVideoTimeCodeFlags {
self.bits()
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
#[doc(hidden)]
impl FromGlib<ffi::GstVideoTimeCodeFlags> for VideoTimeCodeFlags {
fn from_glib(value: ffi::GstVideoTimeCodeFlags) -> VideoTimeCodeFlags {
skip_assert_initialized!();
VideoTimeCodeFlags::from_bits_truncate(value)
}
}
......@@ -28,6 +28,8 @@ pub use self::flags::VideoFormatFlags;
pub use self::flags::VideoFrameFlags;
pub use self::flags::VideoMultiviewFlags;
pub use self::flags::VideoOverlayFormatFlags;
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub use self::flags::VideoTimeCodeFlags;
#[doc(hidden)]
pub mod traits {
......
......@@ -62,6 +62,14 @@ mod video_overlay_composition;
pub use video_overlay_composition::*;
mod video_meta;
pub use video_meta::*;
#[cfg(any(feature = "v1_10", feature = "dox"))]
mod video_time_code;
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub use video_time_code::{ValidVideoTimeCode, VideoTimeCode};
#[cfg(any(feature = "v1_12", feature = "dox"))]
mod video_time_code_interval;
#[cfg(any(feature = "v1_12", feature = "dox"))]
pub use video_time_code_interval::VideoTimeCodeInterval;
// Re-export all the traits in a prelude module, so that applications
// can always "use gst::prelude::*" without getting conflicts
......
This diff is collapsed.
// Copyright (C) 2018 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 ffi;
use glib;
use glib::prelude::*;
use glib::translate::*;
use glib::value;
use glib_ffi;
use gobject_ffi;
use gst;
use std::cmp;
use std::fmt;
use std::mem;
use std::ptr;
#[derive(Clone)]
pub struct VideoTimeCodeInterval(ffi::GstVideoTimeCodeInterval);
impl VideoTimeCodeInterval {
pub fn from_string(tc_inter_str: &str) -> Option<Self> {
assert_initialized_main_thread!();
unsafe {
from_glib_full(ffi::gst_video_time_code_interval_new_from_string(
tc_inter_str.to_glib_none().0,
))
}
}
pub fn new(&mut self, hours: u32, minutes: u32, seconds: u32, frames: u32) -> Self {
assert_initialized_main_thread!();
unsafe {
let mut v = mem::zeroed();
ffi::gst_video_time_code_interval_init(&mut v, hours, minutes, seconds, frames);
VideoTimeCodeInterval(v)
}
}
pub fn get_hours(&self) -> u32 {
self.0.hours
}
pub fn set_hours(&mut self, hours: u32) {
self.0.hours = hours
}
pub fn get_minutes(&self) -> u32 {
self.0.minutes
}
pub fn set_minutes(&mut self, minutes: u32) {
assert!(minutes < 60);
self.0.minutes = minutes
}
pub fn get_seconds(&self) -> u32 {
self.0.seconds
}
pub fn set_seconds(&mut self, seconds: u32) {
assert!(seconds < 60);
self.0.seconds = seconds
}
pub fn get_frames(&self) -> u32 {
self.0.frames
}
pub fn set_frames(&mut self, hours: u32) {
self.0.frames = hours
}
}
unsafe impl Send for VideoTimeCodeInterval {}
unsafe impl Sync for VideoTimeCodeInterval {}
impl PartialEq for VideoTimeCodeInterval {
fn eq(&self, other: &Self) -> bool {
self.0.hours == other.0.hours
&& self.0.minutes == other.0.hours
&& self.0.seconds == other.0.seconds
&& self.0.frames == other.0.frames
}
}
impl Eq for VideoTimeCodeInterval {}
impl PartialOrd for VideoTimeCodeInterval {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for VideoTimeCodeInterval {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.0
.hours
.cmp(&other.0.hours)
.then_with(|| self.0.minutes.cmp(&other.0.hours))
.then_with(|| self.0.seconds.cmp(&other.0.seconds))
.then_with(|| self.0.frames.cmp(&other.0.frames))
}
}
impl fmt::Debug for VideoTimeCodeInterval {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
f.debug_struct("VideoTimeCodeInterval")
.field("hours", &self.0.hours)
.field("minutes", &self.0.minutes)
.field("seconds", &self.0.seconds)
.field("frames", &self.0.frames)
.finish()
}
}
impl fmt::Display for VideoTimeCodeInterval {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
f,
"{:02}:{:02}:{:02}:{:02}",
self.0.hours, self.0.minutes, self.0.seconds, self.0.frames
)
}
}
#[doc(hidden)]
impl GlibPtrDefault for VideoTimeCodeInterval {
type GlibType = *mut ffi::GstVideoTimeCodeInterval;
}
#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval {
type Storage = &'a Self;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstVideoTimeCodeInterval, Self> {
Stash(&self.0 as *const _, self)
}
#[inline]
fn to_glib_full(&self) -> *const ffi::GstVideoTimeCodeInterval {
unsafe { ffi::gst_video_time_code_interval_copy(&self.0 as *const _) }
}
}
#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval {
type Storage = &'a mut Self;
#[inline]
fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GstVideoTimeCodeInterval, Self> {
let ptr = &mut self.0 as *mut _;
StashMut(ptr, self)
}
}
#[doc(hidden)]
impl FromGlibPtrNone<*mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval {
#[inline]
unsafe fn from_glib_none(ptr: *mut ffi::GstVideoTimeCodeInterval) -> Self {
assert!(!ptr.is_null());
VideoTimeCodeInterval(ptr::read(ptr))
}
}
#[doc(hidden)]
impl FromGlibPtrNone<*const ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval {
#[inline]
unsafe fn from_glib_none(ptr: *const ffi::GstVideoTimeCodeInterval) -> Self {
assert!(!ptr.is_null());
VideoTimeCodeInterval(ptr::read(ptr))
}
}
#[doc(hidden)]
impl FromGlibPtrFull<*mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval {
#[inline]
unsafe fn from_glib_full(ptr: *mut ffi::GstVideoTimeCodeInterval) -> Self {
assert!(!ptr.is_null());
let res = VideoTimeCodeInterval(ptr::read(ptr));
ffi::gst_video_time_code_interval_free(ptr);
res
}
}
#[doc(hidden)]
impl FromGlibPtrBorrow<*mut ffi::GstVideoTimeCodeInterval> for VideoTimeCodeInterval {
#[inline]
unsafe fn from_glib_borrow(ptr: *mut ffi::GstVideoTimeCodeInterval) -> Self {
assert!(!ptr.is_null());
VideoTimeCodeInterval(ptr::read(ptr))
}
}
impl StaticType for VideoTimeCodeInterval {
fn static_type() -> glib::Type {
unsafe { from_glib(ffi::gst_video_time_code_interval_get_type()) }
}
}
#[doc(hidden)]
impl<'a> value::FromValueOptional<'a> for VideoTimeCodeInterval {
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
Option::<VideoTimeCodeInterval>::from_glib_full(gobject_ffi::g_value_dup_boxed(
value.to_glib_none().0,
)
as *mut ffi::GstVideoTimeCodeInterval)
}
}
#[doc(hidden)]
impl value::SetValue for VideoTimeCodeInterval {
unsafe fn set_value(value: &mut glib::Value, this: &Self) {
gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
ToGlibPtr::<*const ffi::GstVideoTimeCodeInterval>::to_glib_none(this).0
as glib_ffi::gpointer,
)
}
}
#[doc(hidden)]
impl value::SetValueOptional for VideoTimeCodeInterval {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) {
gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
ToGlibPtr::<*const ffi::GstVideoTimeCodeInterval>::to_glib_none(&this).0
as glib_ffi::gpointer,
)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment