forked from mirrors/gstreamer-rs
video: manually order VideoFormat and VideoFormatInfo
This commit is contained in:
parent
bb065be349
commit
ae57524502
4 changed files with 122 additions and 2 deletions
|
@ -19,7 +19,6 @@ external_libraries = [
|
||||||
|
|
||||||
generate = [
|
generate = [
|
||||||
"GstVideo.VideoCodecFrameFlags",
|
"GstVideo.VideoCodecFrameFlags",
|
||||||
"GstVideo.VideoFormat",
|
|
||||||
"GstVideo.VideoFormatFlags",
|
"GstVideo.VideoFormatFlags",
|
||||||
"GstVideo.VideoTileMode",
|
"GstVideo.VideoTileMode",
|
||||||
"GstVideo.VideoInterlaceMode",
|
"GstVideo.VideoInterlaceMode",
|
||||||
|
@ -242,3 +241,10 @@ manual_traits = ["VideoEncoderExtManual"]
|
||||||
name = "allocate_output_buffer"
|
name = "allocate_output_buffer"
|
||||||
[object.function.return]
|
[object.function.return]
|
||||||
nullable_return_is_error = "Failed to allocate output buffer"
|
nullable_return_is_error = "Failed to allocate output buffer"
|
||||||
|
|
||||||
|
[[object]]
|
||||||
|
name = "GstVideo.VideoFormat"
|
||||||
|
status = "generate"
|
||||||
|
|
||||||
|
[[object.derive]]
|
||||||
|
name = "Debug, Eq, PartialEq, Hash"
|
|
@ -678,7 +678,7 @@ impl SetValue for VideoFieldOrder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum VideoFormat {
|
pub enum VideoFormat {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
|
@ -232,6 +232,19 @@ impl fmt::Display for ::VideoFormat {
|
||||||
f.write_str((*self).to_str())
|
f.write_str((*self).to_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for ::VideoFormat {
|
||||||
|
fn partial_cmp(&self, other: &::VideoFormat) -> Option<std::cmp::Ordering> {
|
||||||
|
::VideoFormatInfo::from_format(*self).partial_cmp(&::VideoFormatInfo::from_format(*other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for ::VideoFormat {
|
||||||
|
fn cmp(&self, other: &::VideoFormat) -> std::cmp::Ordering {
|
||||||
|
::VideoFormatInfo::from_format(*self).cmp(&::VideoFormatInfo::from_format(*other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct VideoFormatIterator {
|
pub struct VideoFormatIterator {
|
||||||
idx: usize,
|
idx: usize,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
@ -372,4 +385,15 @@ mod tests {
|
||||||
.build();
|
.build();
|
||||||
assert_eq!(caps.to_string(), "video/x-raw, format=(string){ NV12, NV16 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]");
|
assert_eq!(caps.to_string(), "video/x-raw, format=(string){ NV12, NV16 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sort() {
|
||||||
|
gst::init().unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
::VideoFormatInfo::from_format(::VideoFormat::Nv16)
|
||||||
|
> ::VideoFormatInfo::from_format(::VideoFormat::Nv12)
|
||||||
|
);
|
||||||
|
assert!(::VideoFormat::I420 > ::VideoFormat::Yv12);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
use gst_video_sys;
|
use gst_video_sys;
|
||||||
|
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
@ -311,6 +312,95 @@ impl PartialEq for VideoFormatInfo {
|
||||||
|
|
||||||
impl Eq for VideoFormatInfo {}
|
impl Eq for VideoFormatInfo {}
|
||||||
|
|
||||||
|
impl PartialOrd for VideoFormatInfo {
|
||||||
|
fn partial_cmp(&self, other: &VideoFormatInfo) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for VideoFormatInfo {
|
||||||
|
// See GST_VIDEO_FORMATS_ALL for the sorting algorithm
|
||||||
|
fn cmp(&self, other: &VideoFormatInfo) -> Ordering {
|
||||||
|
self.n_components()
|
||||||
|
.cmp(&other.n_components())
|
||||||
|
.then_with(|| self.depth().cmp(&other.depth()))
|
||||||
|
.then_with(|| self.w_sub().cmp(&other.w_sub()).reverse())
|
||||||
|
.then_with(|| self.h_sub().cmp(&other.h_sub()).reverse())
|
||||||
|
.then_with(|| self.n_planes().cmp(&other.n_planes()))
|
||||||
|
.then_with(|| {
|
||||||
|
// Format using native endianess is considered as bigger
|
||||||
|
match (
|
||||||
|
self.flags().contains(::VideoFormatFlags::LE),
|
||||||
|
other.flags().contains(::VideoFormatFlags::LE),
|
||||||
|
) {
|
||||||
|
(true, false) => {
|
||||||
|
// a LE, b BE
|
||||||
|
#[cfg(target_endian = "little")]
|
||||||
|
{
|
||||||
|
Ordering::Greater
|
||||||
|
}
|
||||||
|
#[cfg(target_endian = "big")]
|
||||||
|
{
|
||||||
|
Ordering::Less
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(false, true) => {
|
||||||
|
// a BE, b LE
|
||||||
|
#[cfg(target_endian = "little")]
|
||||||
|
{
|
||||||
|
Ordering::Less
|
||||||
|
}
|
||||||
|
#[cfg(target_endian = "big")]
|
||||||
|
{
|
||||||
|
Ordering::Greater
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Ordering::Equal,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then_with(|| self.pixel_stride().cmp(&other.pixel_stride()))
|
||||||
|
.then_with(|| self.poffset().cmp(&other.poffset()))
|
||||||
|
.then_with(|| {
|
||||||
|
// Prefer non-complex formats
|
||||||
|
match (
|
||||||
|
self.flags().contains(::VideoFormatFlags::COMPLEX),
|
||||||
|
other.flags().contains(::VideoFormatFlags::COMPLEX),
|
||||||
|
) {
|
||||||
|
(true, false) => Ordering::Less,
|
||||||
|
(false, true) => Ordering::Greater,
|
||||||
|
_ => Ordering::Equal,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then_with(|| {
|
||||||
|
// tiebreaker: YUV > RGB
|
||||||
|
if self.flags().contains(::VideoFormatFlags::RGB)
|
||||||
|
&& other.flags().contains(::VideoFormatFlags::YUV)
|
||||||
|
{
|
||||||
|
Ordering::Less
|
||||||
|
} else if self.flags().contains(::VideoFormatFlags::YUV)
|
||||||
|
&& other.flags().contains(::VideoFormatFlags::RGB)
|
||||||
|
{
|
||||||
|
Ordering::Greater
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then_with(|| {
|
||||||
|
// Manual tiebreaker
|
||||||
|
match (self.format(), other.format()) {
|
||||||
|
// I420 is more commonly used in GStreamer
|
||||||
|
(::VideoFormat::I420, ::VideoFormat::Yv12) => Ordering::Greater,
|
||||||
|
(::VideoFormat::Yv12, ::VideoFormat::I420) => Ordering::Less,
|
||||||
|
_ => Ordering::Equal,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then_with(|| {
|
||||||
|
// tie, sort by name
|
||||||
|
self.name().cmp(&other.name())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for VideoFormatInfo {
|
impl fmt::Debug for VideoFormatInfo {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
f.debug_struct("VideoFormatInfo")
|
f.debug_struct("VideoFormatInfo")
|
||||||
|
|
Loading…
Reference in a new issue