Implement most of the chroma location API
This commit is contained in:
parent
251c09e732
commit
9ecb233d50
@ -1,6 +1,26 @@
|
||||
use crate::AVPixelFormat;
|
||||
use libc::c_int;
|
||||
|
||||
use crate::{AVChromaLocation, AVPixelFormat};
|
||||
use crate::AVPixelFormat::*;
|
||||
|
||||
impl AVChromaLocation {
|
||||
pub fn from_c_int(n: c_int) -> Option<Self> {
|
||||
use AVChromaLocation as AVCL;
|
||||
|
||||
Some(match n {
|
||||
n if n == AVCL::AVCHROMA_LOC_UNSPECIFIED as c_int => AVCL::AVCHROMA_LOC_UNSPECIFIED,
|
||||
n if n == AVCL::AVCHROMA_LOC_LEFT as c_int => AVCL::AVCHROMA_LOC_LEFT,
|
||||
n if n == AVCL::AVCHROMA_LOC_CENTER as c_int => AVCL::AVCHROMA_LOC_CENTER,
|
||||
n if n == AVCL::AVCHROMA_LOC_TOPLEFT as c_int => AVCL::AVCHROMA_LOC_TOPLEFT,
|
||||
n if n == AVCL::AVCHROMA_LOC_TOP as c_int => AVCL::AVCHROMA_LOC_TOP,
|
||||
n if n == AVCL::AVCHROMA_LOC_BOTTOMLEFT as c_int => AVCL::AVCHROMA_LOC_BOTTOMLEFT,
|
||||
n if n == AVCL::AVCHROMA_LOC_BOTTOM as c_int => AVCL::AVCHROMA_LOC_BOTTOM,
|
||||
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_endian = "little")]
|
||||
pub const AV_PIX_FMT_RGB32: AVPixelFormat = AV_PIX_FMT_BGRA;
|
||||
#[cfg(target_endian = "little")]
|
||||
|
@ -1,5 +1,9 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use crate::ffi::AVChromaLocation::*;
|
||||
use crate::ffi::*;
|
||||
use crate::utils;
|
||||
use crate::Error;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -15,6 +19,55 @@ pub enum Location {
|
||||
Bottom,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
/// Returns the name of this location. Should usually return Some(name).
|
||||
pub fn name(self) -> Option<&'static str> {
|
||||
unsafe { utils::optional_str_from_c_ptr(av_chroma_location_name(self.into())) }
|
||||
}
|
||||
|
||||
/// Returns a chroma location for the given name or an error if the `name` is invalid
|
||||
/// or no location was found.
|
||||
pub fn from_name<S: AsRef<str>>(name: S) -> Result<Self, Error> {
|
||||
let Ok(cstr) = CString::new(name.as_ref()) else {
|
||||
// invalid argument (contains a nul byte)
|
||||
return Err(Error::from(AVERROR(libc::EINVAL)));
|
||||
};
|
||||
|
||||
let ret = unsafe { av_chroma_location_from_name(cstr.as_ptr()) };
|
||||
|
||||
if ret < 0 {
|
||||
Err(Error::from(ret))
|
||||
} else {
|
||||
AVChromaLocation::from_c_int(ret)
|
||||
.map(Location::from)
|
||||
.ok_or(Error::from(AVERROR(libc::EINVAL)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the swscale (x, y) chroma positions for this chroma location.
|
||||
/// Will panic if `self` is [`Unspecified`][Location::Unspecified].
|
||||
#[cfg(feature = "ffmpeg_6_0")]
|
||||
pub fn pos(self) -> (i32, i32) {
|
||||
let mut xpos = 0;
|
||||
let mut ypos = 0;
|
||||
let ret = unsafe { av_chroma_location_enum_to_pos(&mut xpos, &mut ypos, self.into()) };
|
||||
assert_eq!(ret, 0, "av_chroma_location_enum_to_pos returned an error");
|
||||
|
||||
(xpos as i32, ypos as i32)
|
||||
}
|
||||
|
||||
/// Returns a chroma location for the given swscale chroma position.
|
||||
#[cfg(feature = "ffmpeg_6_0")]
|
||||
pub fn from_pos(x: i32, y: i32) -> Self {
|
||||
unsafe {
|
||||
Self::from(av_chroma_location_pos_to_enum(
|
||||
x as libc::c_int,
|
||||
y as libc::c_int,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AVChromaLocation> for Location {
|
||||
fn from(value: AVChromaLocation) -> Self {
|
||||
match value {
|
||||
@ -46,3 +99,50 @@ impl From<Location> for AVChromaLocation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use libc::EINVAL;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn name() {
|
||||
assert_eq!(Location::BottomLeft.name(), Some("bottomleft"));
|
||||
assert_eq!(Location::Center.name(), Some("center"));
|
||||
assert_eq!(Location::Unspecified.name(), Some("unspecified"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_name() {
|
||||
assert_eq!(Location::from_name("topleft"), Ok(Location::TopLeft));
|
||||
assert_eq!(
|
||||
Location::from_name("asdf"),
|
||||
Err(Error::Other { errno: EINVAL })
|
||||
);
|
||||
|
||||
let name = "test".to_string() + "\0something else";
|
||||
|
||||
// important: no panic or segfault!
|
||||
assert_eq!(
|
||||
Location::from_name(name),
|
||||
Err(Error::Other { errno: EINVAL })
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "ffmpeg_6_0")]
|
||||
fn pos() {
|
||||
assert_eq!(Location::BottomLeft.pos(), (0, 256));
|
||||
assert_eq!(Location::Left.pos(), (0, 128));
|
||||
assert_eq!(Location::Center.pos(), (128, 128));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "ffmpeg_6_0")]
|
||||
fn from_pos() {
|
||||
assert_eq!(Location::from_pos(0, 128), Location::Left);
|
||||
assert_eq!(Location::from_pos(128, 0), Location::Top);
|
||||
assert_eq!(Location::from_pos(10, 20), Location::Unspecified);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user