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 = [
|
||||
"GstVideo.VideoCodecFrameFlags",
|
||||
"GstVideo.VideoFormat",
|
||||
"GstVideo.VideoFormatFlags",
|
||||
"GstVideo.VideoTileMode",
|
||||
"GstVideo.VideoInterlaceMode",
|
||||
|
@ -242,3 +241,10 @@ manual_traits = ["VideoEncoderExtManual"]
|
|||
name = "allocate_output_buffer"
|
||||
[object.function.return]
|
||||
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]
|
||||
pub enum VideoFormat {
|
||||
Unknown,
|
||||
|
|
|
@ -232,6 +232,19 @@ impl fmt::Display for ::VideoFormat {
|
|||
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 {
|
||||
idx: usize,
|
||||
len: usize,
|
||||
|
@ -372,4 +385,15 @@ mod tests {
|
|||
.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 ]");
|
||||
}
|
||||
|
||||
#[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 std::cmp::Ordering;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
|
@ -311,6 +312,95 @@ impl PartialEq 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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("VideoFormatInfo")
|
||||
|
|
Loading…
Reference in a new issue