2017-08-11 09:29:23 +00:00
|
|
|
// 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.
|
|
|
|
|
2019-03-19 07:58:20 +00:00
|
|
|
use glib_sys;
|
|
|
|
use gobject_sys;
|
|
|
|
use gst_video_sys;
|
2017-08-11 09:29:23 +00:00
|
|
|
|
|
|
|
use glib;
|
2018-07-27 10:36:40 +00:00
|
|
|
use glib::translate::{
|
2019-10-04 06:11:30 +00:00
|
|
|
from_glib, from_glib_full, from_glib_none, FromGlib, FromGlibPtrFull, FromGlibPtrNone, ToGlib,
|
|
|
|
ToGlibPtr, ToGlibPtrMut,
|
2018-07-27 10:36:40 +00:00
|
|
|
};
|
2018-04-01 08:30:03 +00:00
|
|
|
use gst;
|
|
|
|
use gst::prelude::*;
|
2017-08-11 09:29:23 +00:00
|
|
|
|
2019-10-04 06:11:30 +00:00
|
|
|
use std::ffi::CStr;
|
2018-04-01 08:30:03 +00:00
|
|
|
use std::fmt;
|
2017-08-11 09:29:23 +00:00
|
|
|
use std::mem;
|
|
|
|
use std::ptr;
|
|
|
|
use std::str;
|
|
|
|
|
2019-06-18 08:00:59 +00:00
|
|
|
pub const VIDEO_MAX_PLANES: usize = gst_video_sys::GST_VIDEO_MAX_PLANES as usize;
|
2019-06-18 05:27:58 +00:00
|
|
|
|
2017-08-11 09:29:23 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
|
|
pub enum VideoColorRange {
|
|
|
|
Unknown,
|
|
|
|
Range0255,
|
|
|
|
Range16235,
|
2018-02-22 10:18:37 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
__Unknown(i32),
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl ToGlib for VideoColorRange {
|
2019-03-19 07:58:20 +00:00
|
|
|
type GlibType = gst_video_sys::GstVideoColorRange;
|
2017-08-11 09:29:23 +00:00
|
|
|
|
2019-03-19 07:58:20 +00:00
|
|
|
fn to_glib(&self) -> gst_video_sys::GstVideoColorRange {
|
2017-08-11 09:29:23 +00:00
|
|
|
match *self {
|
2019-03-19 07:58:20 +00:00
|
|
|
VideoColorRange::Unknown => gst_video_sys::GST_VIDEO_COLOR_RANGE_UNKNOWN,
|
|
|
|
VideoColorRange::Range0255 => gst_video_sys::GST_VIDEO_COLOR_RANGE_0_255,
|
|
|
|
VideoColorRange::Range16235 => gst_video_sys::GST_VIDEO_COLOR_RANGE_16_235,
|
2017-11-26 22:13:29 +00:00
|
|
|
VideoColorRange::__Unknown(value) => value,
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
2019-03-19 07:58:20 +00:00
|
|
|
impl FromGlib<gst_video_sys::GstVideoColorRange> for VideoColorRange {
|
|
|
|
fn from_glib(value: gst_video_sys::GstVideoColorRange) -> Self {
|
2017-08-11 09:29:23 +00:00
|
|
|
skip_assert_initialized!();
|
|
|
|
match value as i32 {
|
|
|
|
0 => VideoColorRange::Unknown,
|
|
|
|
1 => VideoColorRange::Range0255,
|
|
|
|
2 => VideoColorRange::Range16235,
|
|
|
|
value => VideoColorRange::__Unknown(value),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl glib::StaticType for VideoColorRange {
|
|
|
|
fn static_type() -> glib::Type {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe { from_glib(gst_video_sys::gst_video_color_range_get_type()) }
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> glib::value::FromValueOptional<'a> for VideoColorRange {
|
|
|
|
unsafe fn from_value_optional(value: &glib::value::Value) -> Option<Self> {
|
|
|
|
Some(glib::value::FromValue::from_value(value))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> glib::value::FromValue<'a> for VideoColorRange {
|
|
|
|
unsafe fn from_value(value: &glib::value::Value) -> Self {
|
2019-03-19 07:58:20 +00:00
|
|
|
from_glib(gobject_sys::g_value_get_enum(value.to_glib_none().0))
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl glib::value::SetValue for VideoColorRange {
|
|
|
|
unsafe fn set_value(value: &mut glib::value::Value, this: &Self) {
|
2019-03-19 07:58:20 +00:00
|
|
|
gobject_sys::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32)
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-19 07:58:20 +00:00
|
|
|
pub struct VideoColorimetry(gst_video_sys::GstVideoColorimetry);
|
2017-08-11 09:29:23 +00:00
|
|
|
|
|
|
|
impl VideoColorimetry {
|
|
|
|
pub fn new(
|
|
|
|
range: VideoColorRange,
|
|
|
|
matrix: ::VideoColorMatrix,
|
|
|
|
transfer: ::VideoTransferFunction,
|
|
|
|
primaries: ::VideoColorPrimaries,
|
|
|
|
) -> Self {
|
2017-08-30 09:48:01 +00:00
|
|
|
assert_initialized_main_thread!();
|
2017-08-11 09:29:23 +00:00
|
|
|
|
|
|
|
let colorimetry = unsafe {
|
2019-03-19 07:58:20 +00:00
|
|
|
let mut colorimetry: gst_video_sys::GstVideoColorimetry = mem::zeroed();
|
2017-08-11 09:29:23 +00:00
|
|
|
|
|
|
|
colorimetry.range = range.to_glib();
|
|
|
|
colorimetry.matrix = matrix.to_glib();
|
|
|
|
colorimetry.transfer = transfer.to_glib();
|
|
|
|
colorimetry.primaries = primaries.to_glib();
|
|
|
|
|
|
|
|
colorimetry
|
|
|
|
};
|
|
|
|
|
|
|
|
VideoColorimetry(colorimetry)
|
|
|
|
}
|
|
|
|
|
2019-01-26 23:42:53 +00:00
|
|
|
pub fn range(&self) -> ::VideoColorRange {
|
|
|
|
from_glib(self.0.range)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn matrix(&self) -> ::VideoColorMatrix {
|
|
|
|
from_glib(self.0.matrix)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn transfer(&self) -> ::VideoTransferFunction {
|
|
|
|
from_glib(self.0.transfer)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn primaries(&self) -> ::VideoColorPrimaries {
|
|
|
|
from_glib(self.0.primaries)
|
|
|
|
}
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Clone for VideoColorimetry {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
unsafe { VideoColorimetry(ptr::read(&self.0)) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for VideoColorimetry {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe {
|
|
|
|
from_glib(gst_video_sys::gst_video_colorimetry_is_equal(
|
|
|
|
&self.0, &other.0,
|
|
|
|
))
|
|
|
|
}
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for VideoColorimetry {}
|
|
|
|
|
|
|
|
impl str::FromStr for ::VideoColorimetry {
|
2019-12-16 11:29:51 +00:00
|
|
|
type Err = glib::error::BoolError;
|
2017-08-11 09:29:23 +00:00
|
|
|
|
2019-12-16 11:29:51 +00:00
|
|
|
fn from_str(s: &str) -> Result<Self, glib::error::BoolError> {
|
2019-10-04 06:11:30 +00:00
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let mut colorimetry = mem::MaybeUninit::zeroed();
|
|
|
|
let valid: bool = from_glib(gst_video_sys::gst_video_colorimetry_from_string(
|
|
|
|
colorimetry.as_mut_ptr(),
|
|
|
|
s.to_glib_none().0,
|
|
|
|
));
|
|
|
|
if valid {
|
|
|
|
Ok(VideoColorimetry(colorimetry.assume_init()))
|
|
|
|
} else {
|
2019-12-16 11:29:51 +00:00
|
|
|
Err(glib_bool_error!("Invalid colorimetry info"))
|
2019-10-04 06:11:30 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for ::VideoColorimetry {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2017-12-16 09:41:48 +00:00
|
|
|
f.debug_struct("VideoColorimetry")
|
|
|
|
.field("range", &self.0.range)
|
|
|
|
.field("matrix", &self.0.matrix)
|
|
|
|
.field("transfer", &self.0.transfer)
|
|
|
|
.field("primaries", &self.0.primaries)
|
|
|
|
.finish()
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for ::VideoColorimetry {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2019-10-04 06:11:30 +00:00
|
|
|
let s = unsafe {
|
|
|
|
glib::GString::from_glib_full(gst_video_sys::gst_video_colorimetry_to_string(&self.0))
|
|
|
|
};
|
|
|
|
f.write_str(&s)
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-16 08:56:19 +00:00
|
|
|
impl From<::VideoMultiviewFramePacking> for ::VideoMultiviewMode {
|
|
|
|
fn from(v: ::VideoMultiviewFramePacking) -> Self {
|
2020-03-22 14:18:47 +00:00
|
|
|
skip_assert_initialized!();
|
2017-12-16 08:56:19 +00:00
|
|
|
from_glib(v.to_glib())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-03 15:42:00 +00:00
|
|
|
impl std::convert::TryFrom<::VideoMultiviewMode> for ::VideoMultiviewFramePacking {
|
2020-05-26 15:53:22 +00:00
|
|
|
type Error = glib::BoolError;
|
2019-06-03 15:42:00 +00:00
|
|
|
|
2020-05-26 15:53:22 +00:00
|
|
|
fn try_from(v: ::VideoMultiviewMode) -> Result<::VideoMultiviewFramePacking, glib::BoolError> {
|
2020-03-22 14:18:47 +00:00
|
|
|
skip_assert_initialized!();
|
|
|
|
|
2017-12-16 08:56:19 +00:00
|
|
|
let v2 = from_glib(v.to_glib());
|
|
|
|
|
|
|
|
if let ::VideoMultiviewFramePacking::__Unknown(_) = v2 {
|
2020-05-26 15:53:22 +00:00
|
|
|
Err(glib_bool_error!("Invalid frame packing mode"))
|
2017-12-16 08:56:19 +00:00
|
|
|
} else {
|
|
|
|
Ok(v2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-19 07:58:20 +00:00
|
|
|
pub struct VideoInfo(pub(crate) gst_video_sys::GstVideoInfo);
|
2017-08-11 09:29:23 +00:00
|
|
|
|
2017-11-06 12:20:50 +00:00
|
|
|
impl fmt::Debug for VideoInfo {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2018-06-08 07:19:25 +00:00
|
|
|
let mut b = f.debug_struct("VideoInfo");
|
|
|
|
|
|
|
|
b.field("format", &self.format())
|
2019-07-03 12:32:43 +00:00
|
|
|
.field("format-info", &self.format_info())
|
2017-11-06 12:20:50 +00:00
|
|
|
.field("width", &self.width())
|
|
|
|
.field("height", &self.height())
|
2018-06-08 07:19:25 +00:00
|
|
|
.field("interlace_mode", &self.interlace_mode())
|
|
|
|
.field("flags", &self.flags())
|
2017-11-06 12:20:50 +00:00
|
|
|
.field("size", &self.size())
|
2018-06-08 07:19:25 +00:00
|
|
|
.field("views", &self.views())
|
|
|
|
.field("chroma_site", &self.chroma_site())
|
|
|
|
.field("colorimetry", &self.colorimetry())
|
|
|
|
.field("par", &self.par())
|
|
|
|
.field("fps", &self.fps())
|
|
|
|
.field("offset", &self.offset())
|
|
|
|
.field("stride", &self.stride())
|
|
|
|
.field("multiview_mode", &self.multiview_mode())
|
|
|
|
.field("multiview_flags", &self.multiview_flags());
|
|
|
|
|
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
|
|
|
{
|
|
|
|
b.field("field_order", &self.field_order());
|
|
|
|
};
|
|
|
|
|
|
|
|
b.finish()
|
2017-11-06 12:20:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-22 15:43:29 +00:00
|
|
|
#[derive(Debug)]
|
2017-08-11 09:29:23 +00:00
|
|
|
pub struct VideoInfoBuilder<'a> {
|
|
|
|
format: ::VideoFormat,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
interlace_mode: Option<::VideoInterlaceMode>,
|
|
|
|
flags: Option<::VideoFlags>,
|
|
|
|
size: Option<usize>,
|
|
|
|
views: Option<u32>,
|
|
|
|
chroma_site: Option<::VideoChromaSite>,
|
|
|
|
colorimetry: Option<&'a ::VideoColorimetry>,
|
|
|
|
par: Option<gst::Fraction>,
|
|
|
|
fps: Option<gst::Fraction>,
|
|
|
|
offset: Option<&'a [usize]>,
|
|
|
|
stride: Option<&'a [i32]>,
|
|
|
|
multiview_mode: Option<::VideoMultiviewMode>,
|
|
|
|
multiview_flags: Option<::VideoMultiviewFlags>,
|
2018-02-22 10:18:37 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
|
|
|
field_order: Option<::VideoFieldOrder>,
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> VideoInfoBuilder<'a> {
|
2019-12-15 08:36:56 +00:00
|
|
|
pub fn build(self) -> Result<VideoInfo, glib::error::BoolError> {
|
2017-08-11 09:29:23 +00:00
|
|
|
unsafe {
|
2019-07-11 12:34:28 +00:00
|
|
|
let mut info = mem::MaybeUninit::uninit();
|
2017-08-11 09:29:23 +00:00
|
|
|
|
2020-02-14 12:12:41 +00:00
|
|
|
#[cfg(not(feature = "v1_12"))]
|
|
|
|
let res: bool = {
|
|
|
|
// The bool return value is new with 1.11.1, see
|
|
|
|
// https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/commit/17cdd369e6f2f73329d27dfceb50011f40f1ceb0
|
|
|
|
let res = if gst::version() < (1, 11, 1, 0) {
|
|
|
|
gst_video_sys::gst_video_info_set_format(
|
|
|
|
info.as_mut_ptr(),
|
|
|
|
self.format.to_glib(),
|
|
|
|
self.width,
|
|
|
|
self.height,
|
|
|
|
);
|
|
|
|
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
from_glib(gst_video_sys::gst_video_info_set_format(
|
|
|
|
info.as_mut_ptr(),
|
|
|
|
self.format.to_glib(),
|
|
|
|
self.width,
|
|
|
|
self.height,
|
|
|
|
))
|
|
|
|
};
|
|
|
|
|
|
|
|
if res {
|
|
|
|
if let Some(interlace_mode) = self.interlace_mode {
|
|
|
|
let info = info.as_mut_ptr();
|
|
|
|
(*info).interlace_mode = interlace_mode.to_glib();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res
|
|
|
|
};
|
|
|
|
#[cfg(all(feature = "v1_12", not(feature = "v1_16")))]
|
2019-07-11 12:34:28 +00:00
|
|
|
let res: bool = {
|
|
|
|
let res = from_glib(gst_video_sys::gst_video_info_set_format(
|
|
|
|
info.as_mut_ptr(),
|
2019-06-26 09:41:47 +00:00
|
|
|
self.format.to_glib(),
|
|
|
|
self.width,
|
|
|
|
self.height,
|
2019-07-11 12:34:28 +00:00
|
|
|
));
|
2019-06-26 09:41:47 +00:00
|
|
|
|
2019-07-11 12:34:28 +00:00
|
|
|
if res {
|
|
|
|
if let Some(interlace_mode) = self.interlace_mode {
|
|
|
|
let info = info.as_mut_ptr();
|
|
|
|
(*info).interlace_mode = interlace_mode.to_glib();
|
|
|
|
}
|
2019-06-26 09:41:47 +00:00
|
|
|
}
|
2019-07-11 12:34:28 +00:00
|
|
|
|
|
|
|
res
|
|
|
|
};
|
2019-06-26 09:41:47 +00:00
|
|
|
#[cfg(feature = "v1_16")]
|
2019-07-11 12:34:28 +00:00
|
|
|
let res: bool = {
|
|
|
|
from_glib(if let Some(interlace_mode) = self.interlace_mode {
|
2019-06-26 09:41:47 +00:00
|
|
|
gst_video_sys::gst_video_info_set_interlaced_format(
|
2019-07-11 12:34:28 +00:00
|
|
|
info.as_mut_ptr(),
|
2019-06-26 09:41:47 +00:00
|
|
|
self.format.to_glib(),
|
|
|
|
interlace_mode.to_glib(),
|
|
|
|
self.width,
|
|
|
|
self.height,
|
2019-07-11 12:34:28 +00:00
|
|
|
)
|
2019-06-26 09:41:47 +00:00
|
|
|
} else {
|
|
|
|
gst_video_sys::gst_video_info_set_format(
|
2019-07-11 12:34:28 +00:00
|
|
|
info.as_mut_ptr(),
|
2019-06-26 09:41:47 +00:00
|
|
|
self.format.to_glib(),
|
|
|
|
self.width,
|
|
|
|
self.height,
|
2019-07-11 12:34:28 +00:00
|
|
|
)
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
if !res {
|
2019-12-15 08:36:56 +00:00
|
|
|
return Err(glib_bool_error!("Failed to build VideoInfo"));
|
2019-06-26 09:41:47 +00:00
|
|
|
}
|
2017-08-11 09:29:23 +00:00
|
|
|
|
2019-07-11 12:34:28 +00:00
|
|
|
let mut info = info.assume_init();
|
|
|
|
|
2018-07-20 07:21:06 +00:00
|
|
|
if info.finfo.is_null() || info.width <= 0 || info.height <= 0 {
|
2019-12-15 08:36:56 +00:00
|
|
|
return Err(glib_bool_error!("Failed to build VideoInfo"));
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(flags) = self.flags {
|
|
|
|
info.flags = flags.to_glib();
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(size) = self.size {
|
|
|
|
info.size = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(views) = self.views {
|
|
|
|
info.views = views as i32;
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(chroma_site) = self.chroma_site {
|
|
|
|
info.chroma_site = chroma_site.to_glib();
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(colorimetry) = self.colorimetry {
|
|
|
|
ptr::write(&mut info.colorimetry, ptr::read(&colorimetry.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(par) = self.par {
|
|
|
|
info.par_n = *par.numer();
|
|
|
|
info.par_d = *par.denom();
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(fps) = self.fps {
|
|
|
|
info.fps_n = *fps.numer();
|
|
|
|
info.fps_d = *fps.denom();
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(offset) = self.offset {
|
|
|
|
if offset.len() != ((*info.finfo).n_planes as usize) {
|
2019-12-15 08:36:56 +00:00
|
|
|
return Err(glib_bool_error!("Failed to build VideoInfo"));
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
2017-09-10 11:27:00 +00:00
|
|
|
let n_planes = (*info.finfo).n_planes as usize;
|
|
|
|
info.offset[..n_planes].copy_from_slice(&offset[..n_planes]);
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(stride) = self.stride {
|
|
|
|
if stride.len() != ((*info.finfo).n_planes as usize) {
|
2019-12-15 08:36:56 +00:00
|
|
|
return Err(glib_bool_error!("Failed to build VideoInfo"));
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
2017-09-10 11:27:00 +00:00
|
|
|
let n_planes = (*info.finfo).n_planes as usize;
|
|
|
|
info.stride[..n_planes].copy_from_slice(&stride[..n_planes]);
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(multiview_mode) = self.multiview_mode {
|
2018-02-07 16:53:12 +00:00
|
|
|
let ptr = &mut info.ABI._gst_reserved as *mut _ as *mut i32;
|
2017-11-26 22:13:29 +00:00
|
|
|
ptr::write(ptr.offset(0), multiview_mode.to_glib());
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(multiview_flags) = self.multiview_flags {
|
2018-02-07 16:53:12 +00:00
|
|
|
let ptr = &mut info.ABI._gst_reserved as *mut _ as *mut u32;
|
2018-04-04 07:46:18 +00:00
|
|
|
ptr::write(ptr.offset(1), multiview_flags.to_glib());
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
2017-08-11 09:29:23 +00:00
|
|
|
{
|
|
|
|
if let Some(field_order) = self.field_order {
|
2018-02-07 16:53:12 +00:00
|
|
|
let ptr = &mut info.ABI._gst_reserved as *mut _ as *mut i32;
|
2017-11-26 22:13:29 +00:00
|
|
|
ptr::write(ptr.offset(2), field_order.to_glib());
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-15 08:36:56 +00:00
|
|
|
Ok(VideoInfo(info))
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn interlace_mode(self, interlace_mode: ::VideoInterlaceMode) -> VideoInfoBuilder<'a> {
|
|
|
|
Self {
|
|
|
|
interlace_mode: Some(interlace_mode),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn flags(self, flags: ::VideoFlags) -> Self {
|
|
|
|
Self {
|
|
|
|
flags: Some(flags),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn size(self, size: usize) -> Self {
|
|
|
|
Self {
|
|
|
|
size: Some(size),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn views(self, views: u32) -> Self {
|
|
|
|
Self {
|
|
|
|
views: Some(views),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn chroma_site(self, chroma_site: ::VideoChromaSite) -> Self {
|
|
|
|
Self {
|
|
|
|
chroma_site: Some(chroma_site),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn colorimetry(self, colorimetry: &'a ::VideoColorimetry) -> VideoInfoBuilder<'a> {
|
|
|
|
Self {
|
|
|
|
colorimetry: Some(colorimetry),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-14 06:54:32 +00:00
|
|
|
pub fn par<T: Into<gst::Fraction>>(self, par: T) -> Self {
|
2017-08-11 09:29:23 +00:00
|
|
|
Self {
|
2017-08-14 06:54:32 +00:00
|
|
|
par: Some(par.into()),
|
2017-08-11 09:29:23 +00:00
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-14 06:54:32 +00:00
|
|
|
pub fn fps<T: Into<gst::Fraction>>(self, fps: T) -> Self {
|
2017-08-11 09:29:23 +00:00
|
|
|
Self {
|
2017-08-14 06:54:32 +00:00
|
|
|
fps: Some(fps.into()),
|
2017-08-11 09:29:23 +00:00
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn offset(self, offset: &'a [usize]) -> VideoInfoBuilder<'a> {
|
|
|
|
Self {
|
|
|
|
offset: Some(offset),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stride(self, stride: &'a [i32]) -> VideoInfoBuilder<'a> {
|
|
|
|
Self {
|
|
|
|
stride: Some(stride),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn multiview_mode(self, multiview_mode: ::VideoMultiviewMode) -> Self {
|
|
|
|
Self {
|
|
|
|
multiview_mode: Some(multiview_mode),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn multiview_flags(self, multiview_flags: ::VideoMultiviewFlags) -> Self {
|
|
|
|
Self {
|
|
|
|
multiview_flags: Some(multiview_flags),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
2017-08-11 09:29:23 +00:00
|
|
|
pub fn field_order(self, field_order: ::VideoFieldOrder) -> Self {
|
|
|
|
Self {
|
|
|
|
field_order: Some(field_order),
|
|
|
|
..self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VideoInfo {
|
2020-06-25 16:22:25 +00:00
|
|
|
pub fn builder<'a>(format: ::VideoFormat, width: u32, height: u32) -> VideoInfoBuilder<'a> {
|
2017-08-30 09:48:01 +00:00
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(not(any(feature = "v1_12", feature = "dox")))]
|
2017-08-11 09:29:23 +00:00
|
|
|
{
|
|
|
|
VideoInfoBuilder {
|
2019-02-21 17:30:36 +00:00
|
|
|
format,
|
|
|
|
width,
|
|
|
|
height,
|
2017-08-11 09:29:23 +00:00
|
|
|
interlace_mode: None,
|
|
|
|
flags: None,
|
|
|
|
size: None,
|
|
|
|
views: None,
|
|
|
|
chroma_site: None,
|
|
|
|
colorimetry: None,
|
|
|
|
par: None,
|
|
|
|
fps: None,
|
|
|
|
offset: None,
|
|
|
|
stride: None,
|
|
|
|
multiview_mode: None,
|
|
|
|
multiview_flags: None,
|
|
|
|
}
|
|
|
|
}
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
2017-08-11 09:29:23 +00:00
|
|
|
{
|
|
|
|
VideoInfoBuilder {
|
2018-07-20 07:21:06 +00:00
|
|
|
format,
|
|
|
|
width,
|
|
|
|
height,
|
2017-08-11 09:29:23 +00:00
|
|
|
interlace_mode: None,
|
|
|
|
flags: None,
|
|
|
|
size: None,
|
|
|
|
views: None,
|
|
|
|
chroma_site: None,
|
|
|
|
colorimetry: None,
|
|
|
|
par: None,
|
|
|
|
fps: None,
|
|
|
|
offset: None,
|
|
|
|
stride: None,
|
|
|
|
multiview_mode: None,
|
|
|
|
multiview_flags: None,
|
|
|
|
field_order: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-07 11:13:39 +00:00
|
|
|
pub fn is_valid(&self) -> bool {
|
|
|
|
!self.0.finfo.is_null() && self.0.width > 0 && self.0.height > 0 && self.0.size > 0
|
|
|
|
}
|
|
|
|
|
2019-12-15 08:36:56 +00:00
|
|
|
pub fn from_caps(caps: &gst::CapsRef) -> Result<Self, glib::error::BoolError> {
|
2017-08-30 11:39:09 +00:00
|
|
|
skip_assert_initialized!();
|
2017-08-30 09:48:01 +00:00
|
|
|
|
2017-08-11 09:29:23 +00:00
|
|
|
unsafe {
|
2019-07-11 12:34:28 +00:00
|
|
|
let mut info = mem::MaybeUninit::uninit();
|
2019-03-19 07:58:20 +00:00
|
|
|
if from_glib(gst_video_sys::gst_video_info_from_caps(
|
2019-07-11 12:34:28 +00:00
|
|
|
info.as_mut_ptr(),
|
2019-03-19 07:58:20 +00:00
|
|
|
caps.as_ptr(),
|
|
|
|
)) {
|
2019-12-15 08:36:56 +00:00
|
|
|
Ok(VideoInfo(info.assume_init()))
|
2017-08-11 09:29:23 +00:00
|
|
|
} else {
|
2019-12-15 08:36:56 +00:00
|
|
|
Err(glib_bool_error!("Failed to create VideoInfo from caps"))
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-15 08:36:56 +00:00
|
|
|
pub fn to_caps(&self) -> Result<gst::Caps, glib::error::BoolError> {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe {
|
2019-12-15 08:36:56 +00:00
|
|
|
let result = from_glib_full(gst_video_sys::gst_video_info_to_caps(
|
2019-03-19 07:58:20 +00:00
|
|
|
&self.0 as *const _ as *mut _,
|
2019-12-15 08:36:56 +00:00
|
|
|
));
|
|
|
|
match result {
|
|
|
|
Some(c) => Ok(c),
|
|
|
|
None => Err(glib_bool_error!("Failed to create caps from VideoInfo")),
|
|
|
|
}
|
2019-03-19 07:58:20 +00:00
|
|
|
}
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn format(&self) -> ::VideoFormat {
|
2020-06-07 11:13:39 +00:00
|
|
|
if self.0.finfo.is_null() {
|
|
|
|
return ::VideoFormat::Unknown;
|
|
|
|
}
|
|
|
|
|
2017-08-11 09:29:23 +00:00
|
|
|
unsafe { from_glib((*self.0.finfo).format) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn format_info(&self) -> ::VideoFormatInfo {
|
|
|
|
::VideoFormatInfo::from_format(self.format())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn width(&self) -> u32 {
|
|
|
|
self.0.width as u32
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn height(&self) -> u32 {
|
|
|
|
self.0.height as u32
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn interlace_mode(&self) -> ::VideoInterlaceMode {
|
|
|
|
from_glib(self.0.interlace_mode)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn flags(&self) -> ::VideoFlags {
|
|
|
|
from_glib(self.0.flags)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn size(&self) -> usize {
|
|
|
|
self.0.size
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn views(&self) -> u32 {
|
|
|
|
self.0.views as u32
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn chroma_site(&self) -> ::VideoChromaSite {
|
|
|
|
from_glib(self.0.chroma_site)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn colorimetry(&self) -> VideoColorimetry {
|
|
|
|
unsafe { VideoColorimetry(ptr::read(&self.0.colorimetry)) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn par(&self) -> gst::Fraction {
|
|
|
|
gst::Fraction::new(self.0.par_n, self.0.par_d)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fps(&self) -> gst::Fraction {
|
|
|
|
gst::Fraction::new(self.0.fps_n, self.0.fps_d)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn offset(&self) -> &[usize] {
|
|
|
|
&self.0.offset[0..(self.format_info().n_planes() as usize)]
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stride(&self) -> &[i32] {
|
|
|
|
&self.0.stride[0..(self.format_info().n_planes() as usize)]
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn multiview_mode(&self) -> ::VideoMultiviewMode {
|
|
|
|
unsafe {
|
2018-02-07 16:53:12 +00:00
|
|
|
let ptr = &self.0.ABI._gst_reserved as *const _ as *const i32;
|
2017-11-26 22:13:29 +00:00
|
|
|
from_glib(ptr::read(ptr.offset(0)))
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn multiview_flags(&self) -> ::VideoMultiviewFlags {
|
|
|
|
unsafe {
|
2018-02-07 16:53:12 +00:00
|
|
|
let ptr = &self.0.ABI._gst_reserved as *const _ as *const u32;
|
2018-04-04 07:46:18 +00:00
|
|
|
from_glib(ptr::read(ptr.offset(1)))
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
2017-08-11 09:29:23 +00:00
|
|
|
pub fn field_order(&self) -> ::VideoFieldOrder {
|
|
|
|
unsafe {
|
2018-02-07 16:53:12 +00:00
|
|
|
let ptr = &self.0.ABI._gst_reserved as *const _ as *const i32;
|
2017-11-26 22:13:29 +00:00
|
|
|
from_glib(ptr::read(ptr.offset(2)))
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-11 09:51:27 +00:00
|
|
|
|
|
|
|
pub fn has_alpha(&self) -> bool {
|
|
|
|
self.format_info().has_alpha()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_gray(&self) -> bool {
|
|
|
|
self.format_info().is_gray()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_rgb(&self) -> bool {
|
|
|
|
self.format_info().is_rgb()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_yuv(&self) -> bool {
|
|
|
|
self.format_info().is_yuv()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_interlaced(&self) -> bool {
|
|
|
|
self.interlace_mode() != ::VideoInterlaceMode::Progressive
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn n_planes(&self) -> u32 {
|
|
|
|
self.format_info().n_planes()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn n_components(&self) -> u32 {
|
|
|
|
self.format_info().n_components()
|
|
|
|
}
|
2017-08-11 09:54:01 +00:00
|
|
|
|
2017-12-09 16:20:21 +00:00
|
|
|
pub fn convert<V: Into<gst::GenericFormattedValue>, U: gst::SpecificFormattedValue>(
|
2017-08-11 09:54:01 +00:00
|
|
|
&self,
|
2017-11-11 10:21:55 +00:00
|
|
|
src_val: V,
|
2017-12-09 16:20:21 +00:00
|
|
|
) -> Option<U> {
|
2017-08-30 09:48:01 +00:00
|
|
|
skip_assert_initialized!();
|
|
|
|
|
2017-11-11 10:21:55 +00:00
|
|
|
let src_val = src_val.into();
|
2017-12-09 16:20:21 +00:00
|
|
|
unsafe {
|
2019-07-11 12:34:28 +00:00
|
|
|
let mut dest_val = mem::MaybeUninit::uninit();
|
2019-03-19 07:58:20 +00:00
|
|
|
if from_glib(gst_video_sys::gst_video_info_convert(
|
2017-12-09 16:20:21 +00:00
|
|
|
&self.0 as *const _ as *mut _,
|
|
|
|
src_val.get_format().to_glib(),
|
2017-12-10 10:10:25 +00:00
|
|
|
src_val.to_raw_value(),
|
2017-12-09 16:20:21 +00:00
|
|
|
U::get_default_format().to_glib(),
|
2019-07-11 12:34:28 +00:00
|
|
|
dest_val.as_mut_ptr(),
|
2017-12-09 16:20:21 +00:00
|
|
|
)) {
|
2019-07-11 12:34:28 +00:00
|
|
|
Some(U::from_raw(U::get_default_format(), dest_val.assume_init()))
|
2017-12-09 16:20:21 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-11 10:21:55 +00:00
|
|
|
|
2017-12-09 16:20:21 +00:00
|
|
|
pub fn convert_generic<V: Into<gst::GenericFormattedValue>>(
|
|
|
|
&self,
|
|
|
|
src_val: V,
|
|
|
|
dest_fmt: gst::Format,
|
|
|
|
) -> Option<gst::GenericFormattedValue> {
|
|
|
|
skip_assert_initialized!();
|
|
|
|
|
|
|
|
let src_val = src_val.into();
|
2017-08-11 09:54:01 +00:00
|
|
|
unsafe {
|
2019-07-11 12:34:28 +00:00
|
|
|
let mut dest_val = mem::MaybeUninit::uninit();
|
2019-03-19 07:58:20 +00:00
|
|
|
if from_glib(gst_video_sys::gst_video_info_convert(
|
2017-08-11 09:54:01 +00:00
|
|
|
&self.0 as *const _ as *mut _,
|
2017-12-09 16:20:21 +00:00
|
|
|
src_val.get_format().to_glib(),
|
2017-12-10 10:10:25 +00:00
|
|
|
src_val.to_raw_value(),
|
2017-08-11 09:54:01 +00:00
|
|
|
dest_fmt.to_glib(),
|
2019-07-11 12:34:28 +00:00
|
|
|
dest_val.as_mut_ptr(),
|
2017-08-11 09:54:01 +00:00
|
|
|
)) {
|
2019-07-11 12:34:28 +00:00
|
|
|
Some(gst::GenericFormattedValue::new(
|
|
|
|
dest_fmt,
|
|
|
|
dest_val.assume_init(),
|
|
|
|
))
|
2017-08-11 09:54:01 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-17 11:24:11 +00:00
|
|
|
|
|
|
|
pub fn align(&mut self, align: &mut ::VideoAlignment) -> bool {
|
2020-02-14 12:12:41 +00:00
|
|
|
#[cfg(not(feature = "v1_12"))]
|
|
|
|
unsafe {
|
|
|
|
// The bool return value is new with 1.11.1, see
|
|
|
|
// https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/commit/17cdd369e6f2f73329d27dfceb50011f40f1ceb0
|
|
|
|
if gst::version() < (1, 11, 1, 0) {
|
|
|
|
gst_video_sys::gst_video_info_align(&mut self.0, &mut align.0);
|
|
|
|
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
from_glib(gst_video_sys::gst_video_info_align(
|
|
|
|
&mut self.0,
|
|
|
|
&mut align.0,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(feature = "v1_12")]
|
2019-06-17 11:24:11 +00:00
|
|
|
unsafe {
|
|
|
|
from_glib(gst_video_sys::gst_video_info_align(
|
|
|
|
&mut self.0,
|
|
|
|
&mut align.0,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Clone for VideoInfo {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
unsafe { VideoInfo(ptr::read(&self.0)) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for VideoInfo {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe { from_glib(gst_video_sys::gst_video_info_is_equal(&self.0, &other.0)) }
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for VideoInfo {}
|
|
|
|
|
2017-08-15 14:34:32 +00:00
|
|
|
unsafe impl Send for VideoInfo {}
|
2018-09-22 07:56:25 +00:00
|
|
|
unsafe impl Sync for VideoInfo {}
|
2017-08-15 14:34:32 +00:00
|
|
|
|
2017-08-11 09:29:23 +00:00
|
|
|
impl glib::types::StaticType for VideoInfo {
|
|
|
|
fn static_type() -> glib::types::Type {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe { glib::translate::from_glib(gst_video_sys::gst_video_info_get_type()) }
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl<'a> glib::value::FromValueOptional<'a> for VideoInfo {
|
|
|
|
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
|
2019-03-19 07:58:20 +00:00
|
|
|
Option::<VideoInfo>::from_glib_none(gobject_sys::g_value_get_boxed(value.to_glib_none().0)
|
|
|
|
as *mut gst_video_sys::GstVideoInfo)
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl glib::value::SetValue for VideoInfo {
|
|
|
|
unsafe fn set_value(value: &mut glib::Value, this: &Self) {
|
2019-03-19 07:58:20 +00:00
|
|
|
gobject_sys::g_value_set_boxed(
|
2017-08-11 09:29:23 +00:00
|
|
|
value.to_glib_none_mut().0,
|
2019-03-19 07:58:20 +00:00
|
|
|
glib::translate::ToGlibPtr::<*const gst_video_sys::GstVideoInfo>::to_glib_none(this).0
|
|
|
|
as glib_sys::gpointer,
|
2017-08-11 09:29:23 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl glib::value::SetValueOptional for VideoInfo {
|
|
|
|
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) {
|
2019-03-19 07:58:20 +00:00
|
|
|
gobject_sys::g_value_set_boxed(
|
2017-08-11 09:29:23 +00:00
|
|
|
value.to_glib_none_mut().0,
|
2019-03-19 07:58:20 +00:00
|
|
|
glib::translate::ToGlibPtr::<*const gst_video_sys::GstVideoInfo>::to_glib_none(&this).0
|
|
|
|
as glib_sys::gpointer,
|
2017-08-11 09:29:23 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl glib::translate::Uninitialized for VideoInfo {
|
|
|
|
unsafe fn uninitialized() -> Self {
|
|
|
|
mem::zeroed()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl glib::translate::GlibPtrDefault for VideoInfo {
|
2019-03-19 07:58:20 +00:00
|
|
|
type GlibType = *mut gst_video_sys::GstVideoInfo;
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
2019-03-19 07:58:20 +00:00
|
|
|
impl<'a> glib::translate::ToGlibPtr<'a, *const gst_video_sys::GstVideoInfo> for VideoInfo {
|
2017-08-11 09:29:23 +00:00
|
|
|
type Storage = &'a VideoInfo;
|
|
|
|
|
2019-03-19 07:58:20 +00:00
|
|
|
fn to_glib_none(
|
|
|
|
&'a self,
|
|
|
|
) -> glib::translate::Stash<'a, *const gst_video_sys::GstVideoInfo, Self> {
|
2017-08-11 09:29:23 +00:00
|
|
|
glib::translate::Stash(&self.0, self)
|
|
|
|
}
|
|
|
|
|
2019-03-19 07:58:20 +00:00
|
|
|
fn to_glib_full(&self) -> *const gst_video_sys::GstVideoInfo {
|
2017-08-11 09:29:23 +00:00
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
2019-03-19 07:58:20 +00:00
|
|
|
impl glib::translate::FromGlibPtrNone<*mut gst_video_sys::GstVideoInfo> for VideoInfo {
|
2017-08-11 09:29:23 +00:00
|
|
|
#[inline]
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe fn from_glib_none(ptr: *mut gst_video_sys::GstVideoInfo) -> Self {
|
2017-08-11 09:29:23 +00:00
|
|
|
VideoInfo(ptr::read(ptr))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
2019-03-19 07:58:20 +00:00
|
|
|
impl glib::translate::FromGlibPtrFull<*mut gst_video_sys::GstVideoInfo> for VideoInfo {
|
2017-08-11 09:29:23 +00:00
|
|
|
#[inline]
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe fn from_glib_full(ptr: *mut gst_video_sys::GstVideoInfo) -> Self {
|
2017-08-11 09:29:23 +00:00
|
|
|
let info = from_glib_none(ptr);
|
2019-03-19 07:58:20 +00:00
|
|
|
glib_sys::g_free(ptr as *mut _);
|
2017-08-11 09:29:23 +00:00
|
|
|
info
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
2017-08-11 11:55:31 +00:00
|
|
|
impl ::VideoFieldOrder {
|
2019-10-04 06:11:30 +00:00
|
|
|
pub fn to_str<'a>(self) -> &'a str {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe {
|
2019-10-04 06:11:30 +00:00
|
|
|
CStr::from_ptr(gst_video_sys::gst_video_field_order_to_string(
|
2019-03-19 07:58:20 +00:00
|
|
|
self.to_glib(),
|
|
|
|
))
|
2019-10-04 06:11:30 +00:00
|
|
|
.to_str()
|
|
|
|
.unwrap()
|
2019-03-19 07:58:20 +00:00
|
|
|
}
|
2017-08-11 11:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
2017-08-11 11:55:31 +00:00
|
|
|
impl str::FromStr for ::VideoFieldOrder {
|
2019-12-16 11:29:51 +00:00
|
|
|
type Err = glib::error::BoolError;
|
2017-08-11 11:55:31 +00:00
|
|
|
|
2019-12-16 11:29:51 +00:00
|
|
|
fn from_str(s: &str) -> Result<Self, glib::error::BoolError> {
|
2019-10-04 06:11:30 +00:00
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
Ok(from_glib(gst_video_sys::gst_video_field_order_from_string(
|
|
|
|
s.to_glib_none().0,
|
|
|
|
)))
|
|
|
|
}
|
2017-08-11 11:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-12 12:33:02 +00:00
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
2017-08-11 11:55:31 +00:00
|
|
|
impl fmt::Display for ::VideoFieldOrder {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2019-10-04 06:11:30 +00:00
|
|
|
f.write_str((*self).to_str())
|
2017-08-11 11:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::VideoInterlaceMode {
|
2019-10-04 06:11:30 +00:00
|
|
|
pub fn to_str<'a>(self) -> &'a str {
|
2019-03-19 07:58:20 +00:00
|
|
|
unsafe {
|
2019-10-04 06:11:30 +00:00
|
|
|
CStr::from_ptr(gst_video_sys::gst_video_interlace_mode_to_string(
|
2019-03-19 07:58:20 +00:00
|
|
|
self.to_glib(),
|
|
|
|
))
|
2019-10-04 06:11:30 +00:00
|
|
|
.to_str()
|
|
|
|
.unwrap()
|
2017-08-11 11:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl str::FromStr for ::VideoInterlaceMode {
|
2019-12-16 11:29:51 +00:00
|
|
|
type Err = glib::error::BoolError;
|
2017-08-11 11:55:31 +00:00
|
|
|
|
2019-12-16 11:29:51 +00:00
|
|
|
fn from_str(s: &str) -> Result<Self, glib::error::BoolError> {
|
2019-10-04 06:11:30 +00:00
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
Ok(from_glib(
|
|
|
|
gst_video_sys::gst_video_interlace_mode_from_string(s.to_glib_none().0),
|
|
|
|
))
|
|
|
|
}
|
2017-08-11 11:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for ::VideoInterlaceMode {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2019-10-04 06:11:30 +00:00
|
|
|
f.write_str((*self).to_str())
|
2017-08-11 11:55:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 09:29:23 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use gst;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_new() {
|
|
|
|
gst::init().unwrap();
|
|
|
|
|
2020-06-25 16:22:25 +00:00
|
|
|
let info = VideoInfo::builder(::VideoFormat::I420, 320, 240)
|
2017-08-11 09:29:23 +00:00
|
|
|
.build()
|
|
|
|
.unwrap();
|
|
|
|
assert_eq!(info.format(), ::VideoFormat::I420);
|
|
|
|
assert_eq!(info.width(), 320);
|
|
|
|
assert_eq!(info.height(), 240);
|
|
|
|
assert_eq!(info.size(), 320 * 240 + 2 * 160 * 120);
|
|
|
|
assert_eq!(info.multiview_mode(), ::VideoMultiviewMode::None);
|
|
|
|
assert_eq!(&info.offset(), &[0, 320 * 240, 320 * 240 + 160 * 120]);
|
|
|
|
assert_eq!(&info.stride(), &[320, 160, 160]);
|
|
|
|
|
|
|
|
let offsets = [0, 640 * 240 + 16, 640 * 240 + 16 + 320 * 120 + 16];
|
|
|
|
let strides = [640, 320, 320];
|
2020-06-25 16:22:25 +00:00
|
|
|
let info = VideoInfo::builder(::VideoFormat::I420, 320, 240)
|
2017-08-11 09:29:23 +00:00
|
|
|
.offset(&offsets)
|
|
|
|
.stride(&strides)
|
|
|
|
.size(640 * 240 + 16 + 320 * 120 + 16 + 320 * 120 + 16)
|
|
|
|
.multiview_mode(::VideoMultiviewMode::SideBySide)
|
|
|
|
.build()
|
|
|
|
.unwrap();
|
|
|
|
assert_eq!(info.format(), ::VideoFormat::I420);
|
|
|
|
assert_eq!(info.width(), 320);
|
|
|
|
assert_eq!(info.height(), 240);
|
|
|
|
assert_eq!(
|
|
|
|
info.size(),
|
|
|
|
640 * 240 + 16 + 320 * 120 + 16 + 320 * 120 + 16
|
|
|
|
);
|
|
|
|
assert_eq!(info.multiview_mode(), ::VideoMultiviewMode::SideBySide);
|
|
|
|
assert_eq!(
|
|
|
|
&info.offset(),
|
|
|
|
&[0, 640 * 240 + 16, 640 * 240 + 16 + 320 * 120 + 16]
|
|
|
|
);
|
|
|
|
assert_eq!(&info.stride(), &[640, 320, 320]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from_to_caps() {
|
|
|
|
gst::init().unwrap();
|
|
|
|
|
|
|
|
let caps = gst::Caps::new_simple(
|
|
|
|
"video/x-raw",
|
|
|
|
&[
|
|
|
|
("format", &"I420"),
|
|
|
|
("width", &320),
|
|
|
|
("height", &240),
|
|
|
|
("framerate", &gst::Fraction::new(30, 1)),
|
|
|
|
("pixel-aspect-ratio", &gst::Fraction::new(1, 1)),
|
|
|
|
("interlace-mode", &"progressive"),
|
|
|
|
("chroma-site", &"mpeg2"),
|
|
|
|
("colorimetry", &"bt709"),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
let info = VideoInfo::from_caps(&caps).unwrap();
|
|
|
|
assert_eq!(info.format(), ::VideoFormat::I420);
|
|
|
|
assert_eq!(info.width(), 320);
|
|
|
|
assert_eq!(info.height(), 240);
|
|
|
|
assert_eq!(info.fps(), gst::Fraction::new(30, 1));
|
|
|
|
assert_eq!(info.interlace_mode(), ::VideoInterlaceMode::Progressive);
|
2017-10-01 14:02:29 +00:00
|
|
|
assert_eq!(info.chroma_site(), ::VideoChromaSite::MPEG2);
|
2017-08-11 09:29:23 +00:00
|
|
|
assert_eq!(info.colorimetry(), "bt709".parse().unwrap());
|
|
|
|
|
|
|
|
let caps2 = info.to_caps().unwrap();
|
|
|
|
assert_eq!(caps, caps2);
|
|
|
|
|
|
|
|
let info2 = VideoInfo::from_caps(&caps2).unwrap();
|
|
|
|
assert!(info == info2);
|
|
|
|
}
|
2019-06-17 11:24:11 +00:00
|
|
|
|
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
|
|
|
#[test]
|
|
|
|
fn test_video_align() {
|
|
|
|
gst::init().unwrap();
|
|
|
|
|
2020-06-25 16:22:25 +00:00
|
|
|
let mut info = ::VideoInfo::builder(::VideoFormat::Nv16, 1920, 1080)
|
2019-06-17 11:24:11 +00:00
|
|
|
.build()
|
|
|
|
.expect("Failed to create VideoInfo");
|
|
|
|
|
|
|
|
assert_eq!(info.stride(), [1920, 1920]);
|
2019-12-22 07:59:23 +00:00
|
|
|
assert_eq!(info.offset(), [0, 2_073_600]);
|
2019-06-17 11:24:11 +00:00
|
|
|
|
2019-06-18 08:00:59 +00:00
|
|
|
let mut align = ::VideoAlignment::new(0, 0, 0, 8, &[0; VIDEO_MAX_PLANES]);
|
2019-06-17 11:24:11 +00:00
|
|
|
assert!(info.align(&mut align));
|
|
|
|
|
|
|
|
assert_eq!(info.stride(), [1928, 1928]);
|
2019-12-22 07:59:23 +00:00
|
|
|
assert_eq!(info.offset(), [0, 2_082_240]);
|
2019-06-17 11:24:11 +00:00
|
|
|
}
|
2019-06-18 10:15:33 +00:00
|
|
|
|
|
|
|
#[cfg(any(feature = "v1_12", feature = "dox"))]
|
|
|
|
#[test]
|
|
|
|
fn test_display() {
|
2019-10-04 06:11:30 +00:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
2019-06-18 10:15:33 +00:00
|
|
|
gst::init().unwrap();
|
|
|
|
|
2019-10-04 06:11:30 +00:00
|
|
|
format!("{}", ::VideoColorimetry::from_str("sRGB").unwrap());
|
2019-06-18 10:15:33 +00:00
|
|
|
format!("{}", ::VideoFieldOrder::TopFieldFirst);
|
|
|
|
format!("{}", ::VideoInterlaceMode::Progressive);
|
|
|
|
}
|
2017-08-11 09:29:23 +00:00
|
|
|
}
|