mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-25 19:11:06 +00:00
video: Add support for static HDR metadata
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/270
This commit is contained in:
parent
c2a2549b66
commit
4e235b0492
2 changed files with 351 additions and 0 deletions
|
@ -103,6 +103,13 @@ pub mod video_codec_state;
|
||||||
pub use crate::video_codec_state::{VideoCodecState, VideoCodecStateContext};
|
pub use crate::video_codec_state::{VideoCodecState, VideoCodecStateContext};
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "v1_18", feature = "dox"))]
|
||||||
|
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
|
||||||
|
mod video_hdr;
|
||||||
|
#[cfg(any(feature = "v1_18", feature = "dox"))]
|
||||||
|
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
|
||||||
|
pub use crate::video_hdr::*;
|
||||||
|
|
||||||
pub const VIDEO_ENCODER_FLOW_NEED_DATA: gst::FlowSuccess = gst::FlowSuccess::CustomSuccess;
|
pub const VIDEO_ENCODER_FLOW_NEED_DATA: gst::FlowSuccess = gst::FlowSuccess::CustomSuccess;
|
||||||
pub const VIDEO_DECODER_FLOW_NEED_DATA: gst::FlowSuccess = gst::FlowSuccess::CustomSuccess;
|
pub const VIDEO_DECODER_FLOW_NEED_DATA: gst::FlowSuccess = gst::FlowSuccess::CustomSuccess;
|
||||||
|
|
||||||
|
|
344
gstreamer-video/src/video_hdr.rs
Normal file
344
gstreamer-video/src/video_hdr.rs
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||||
|
|
||||||
|
use glib::translate::*;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::fmt;
|
||||||
|
use std::mem;
|
||||||
|
use std::ptr;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[doc(alias = "GstVideoContentLightLevel")]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct VideoContentLightLevel(ffi::GstVideoContentLightLevel);
|
||||||
|
|
||||||
|
impl VideoContentLightLevel {
|
||||||
|
pub fn new(max_content_light_level: u16, max_frame_average_light_level: u16) -> Self {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
|
||||||
|
VideoContentLightLevel(ffi::GstVideoContentLightLevel {
|
||||||
|
max_content_light_level,
|
||||||
|
max_frame_average_light_level,
|
||||||
|
_gst_reserved: [ptr::null_mut(); 4],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_content_light_level(&self) -> u16 {
|
||||||
|
self.0.max_content_light_level
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_max_content_light_level(&mut self, max_content_light_level: u16) {
|
||||||
|
self.0.max_content_light_level = max_content_light_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_frame_average_light_level(&self) -> u16 {
|
||||||
|
self.0.max_frame_average_light_level
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_max_frame_average_light_level(&mut self, max_frame_average_light_level: u16) {
|
||||||
|
self.0.max_frame_average_light_level = max_frame_average_light_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_video_content_light_level_add_to_caps")]
|
||||||
|
pub fn add_to_caps(&self, caps: &mut gst::CapsRef) {
|
||||||
|
unsafe {
|
||||||
|
ffi::gst_video_content_light_level_add_to_caps(&self.0, caps.as_mut_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_video_content_light_level_from_caps")]
|
||||||
|
pub fn from_caps(caps: &gst::CapsRef) -> Result<Self, glib::BoolError> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut info = mem::MaybeUninit::zeroed();
|
||||||
|
let res: bool = from_glib(ffi::gst_video_content_light_level_from_caps(
|
||||||
|
info.as_mut_ptr(),
|
||||||
|
caps.as_ptr(),
|
||||||
|
));
|
||||||
|
|
||||||
|
if res {
|
||||||
|
Ok(VideoContentLightLevel(info.assume_init()))
|
||||||
|
} else {
|
||||||
|
Err(glib::bool_error!(
|
||||||
|
"Failed to parse VideoContentLightLevel from caps"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a gst::CapsRef> for VideoContentLightLevel {
|
||||||
|
type Error = glib::BoolError;
|
||||||
|
|
||||||
|
fn try_from(value: &'a gst::CapsRef) -> Result<Self, Self::Error> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
|
||||||
|
Self::from_caps(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for VideoContentLightLevel {
|
||||||
|
#[doc(alias = "gst_video_content_light_level_is_equal")]
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
#[cfg(feature = "v1_20")]
|
||||||
|
unsafe {
|
||||||
|
from_glib(ffi::gst_video_content_light_level_is_equal(
|
||||||
|
&self.0, &other.0,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "v1_20"))]
|
||||||
|
{
|
||||||
|
self.0.max_content_light_level == other.0.max_content_light_level
|
||||||
|
&& self.0.max_frame_average_light_level == other.0.max_frame_average_light_level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for VideoContentLightLevel {}
|
||||||
|
|
||||||
|
impl str::FromStr for VideoContentLightLevel {
|
||||||
|
type Err = glib::error::BoolError;
|
||||||
|
|
||||||
|
#[doc(alias = "gst_video_content_light_level_from_string")]
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut colorimetry = mem::MaybeUninit::zeroed();
|
||||||
|
let valid: bool = from_glib(ffi::gst_video_content_light_level_from_string(
|
||||||
|
colorimetry.as_mut_ptr(),
|
||||||
|
s.to_glib_none().0,
|
||||||
|
));
|
||||||
|
if valid {
|
||||||
|
Ok(Self(colorimetry.assume_init()))
|
||||||
|
} else {
|
||||||
|
Err(glib::bool_error!("Invalid colorimetry info"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for VideoContentLightLevel {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("VideoContentLightLevel")
|
||||||
|
.field("max_content_light_level", &self.0.max_content_light_level)
|
||||||
|
.field(
|
||||||
|
"max_frame_average_light_level",
|
||||||
|
&self.0.max_frame_average_light_level,
|
||||||
|
)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for VideoContentLightLevel {
|
||||||
|
#[doc(alias = "gst_video_content_light_level_to_string")]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let s = unsafe {
|
||||||
|
glib::GString::from_glib_full(ffi::gst_video_content_light_level_to_string(&self.0))
|
||||||
|
};
|
||||||
|
f.write_str(&s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "GstVideoMasteringDisplayInfo")]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct VideoMasteringDisplayInfo(ffi::GstVideoMasteringDisplayInfo);
|
||||||
|
|
||||||
|
impl VideoMasteringDisplayInfo {
|
||||||
|
pub fn new(
|
||||||
|
display_primaries: [VideoMasteringDisplayInfoCoordinate; 3],
|
||||||
|
white_point: VideoMasteringDisplayInfoCoordinate,
|
||||||
|
max_display_mastering_luminance: u32,
|
||||||
|
min_display_mastering_luminance: u32,
|
||||||
|
) -> Self {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
|
||||||
|
VideoMasteringDisplayInfo(ffi::GstVideoMasteringDisplayInfo {
|
||||||
|
display_primaries: unsafe { mem::transmute(display_primaries) },
|
||||||
|
white_point: unsafe { mem::transmute(white_point) },
|
||||||
|
max_display_mastering_luminance,
|
||||||
|
min_display_mastering_luminance,
|
||||||
|
_gst_reserved: [ptr::null_mut(); 4],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn display_primaries(&self) -> [VideoMasteringDisplayInfoCoordinate; 3] {
|
||||||
|
unsafe { mem::transmute(self.0.display_primaries) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_display_primaries(
|
||||||
|
&mut self,
|
||||||
|
display_primaries: [VideoMasteringDisplayInfoCoordinate; 3],
|
||||||
|
) {
|
||||||
|
self.0.display_primaries = unsafe { mem::transmute(display_primaries) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn white_point(&self) -> VideoMasteringDisplayInfoCoordinate {
|
||||||
|
unsafe { mem::transmute(self.0.white_point) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_white_point(&mut self, white_point: VideoMasteringDisplayInfoCoordinate) {
|
||||||
|
self.0.white_point = unsafe { mem::transmute(white_point) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_display_mastering_luminance(&self) -> u32 {
|
||||||
|
self.0.max_display_mastering_luminance
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_max_display_mastering_luminance(&mut self, max_display_mastering_luminance: u32) {
|
||||||
|
self.0.max_display_mastering_luminance = max_display_mastering_luminance;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min_display_mastering_luminance(&self) -> u32 {
|
||||||
|
self.0.min_display_mastering_luminance
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_min_display_mastering_luminance(&mut self, min_display_mastering_luminance: u32) {
|
||||||
|
self.0.min_display_mastering_luminance = min_display_mastering_luminance;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_video_mastering_display_info_add_to_caps")]
|
||||||
|
pub fn add_to_caps(&self, caps: &mut gst::CapsRef) {
|
||||||
|
unsafe {
|
||||||
|
ffi::gst_video_mastering_display_info_add_to_caps(&self.0, caps.as_mut_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_video_mastering_display_info_from_caps")]
|
||||||
|
pub fn from_caps(caps: &gst::CapsRef) -> Result<Self, glib::BoolError> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut info = mem::MaybeUninit::zeroed();
|
||||||
|
let res: bool = from_glib(ffi::gst_video_mastering_display_info_from_caps(
|
||||||
|
info.as_mut_ptr(),
|
||||||
|
caps.as_ptr(),
|
||||||
|
));
|
||||||
|
|
||||||
|
if res {
|
||||||
|
Ok(VideoMasteringDisplayInfo(info.assume_init()))
|
||||||
|
} else {
|
||||||
|
Err(glib::bool_error!(
|
||||||
|
"Failed to parse VideoMasteringDisplayInfo from caps"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a gst::CapsRef> for VideoMasteringDisplayInfo {
|
||||||
|
type Error = glib::BoolError;
|
||||||
|
|
||||||
|
fn try_from(value: &'a gst::CapsRef) -> Result<Self, Self::Error> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
|
||||||
|
Self::from_caps(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for VideoMasteringDisplayInfo {
|
||||||
|
#[doc(alias = "gst_video_mastering_display_info_is_equal")]
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
unsafe {
|
||||||
|
from_glib(ffi::gst_video_mastering_display_info_is_equal(
|
||||||
|
&self.0, &other.0,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for VideoMasteringDisplayInfo {}
|
||||||
|
|
||||||
|
impl str::FromStr for VideoMasteringDisplayInfo {
|
||||||
|
type Err = glib::error::BoolError;
|
||||||
|
|
||||||
|
#[doc(alias = "gst_video_mastering_display_info_from_string")]
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut colorimetry = mem::MaybeUninit::zeroed();
|
||||||
|
let valid: bool = from_glib(ffi::gst_video_mastering_display_info_from_string(
|
||||||
|
colorimetry.as_mut_ptr(),
|
||||||
|
s.to_glib_none().0,
|
||||||
|
));
|
||||||
|
if valid {
|
||||||
|
Ok(Self(colorimetry.assume_init()))
|
||||||
|
} else {
|
||||||
|
Err(glib::bool_error!("Invalid colorimetry info"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for VideoMasteringDisplayInfo {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("VideoMasteringDisplayInfo")
|
||||||
|
.field("display_primaries", &self.display_primaries())
|
||||||
|
.field("white_point", &self.white_point())
|
||||||
|
.field(
|
||||||
|
"max_display_mastering_luminance",
|
||||||
|
&self.0.max_display_mastering_luminance,
|
||||||
|
)
|
||||||
|
.field(
|
||||||
|
"min_display_mastering_luminance",
|
||||||
|
&self.0.min_display_mastering_luminance,
|
||||||
|
)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for VideoMasteringDisplayInfo {
|
||||||
|
#[doc(alias = "gst_video_mastering_display_info_to_string")]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let s = unsafe {
|
||||||
|
glib::GString::from_glib_full(ffi::gst_video_mastering_display_info_to_string(&self.0))
|
||||||
|
};
|
||||||
|
f.write_str(&s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[doc(alias = "GstVideoMasteringDisplayInfoCoordinates")]
|
||||||
|
pub struct VideoMasteringDisplayInfoCoordinate {
|
||||||
|
pub x: u16,
|
||||||
|
pub y: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VideoMasteringDisplayInfoCoordinate {
|
||||||
|
pub fn new(x: f32, y: f32) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
x: (x * 50000.0) as u16,
|
||||||
|
y: (y * 50000.0) as u16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn x(&self) -> f32 {
|
||||||
|
self.x as f32 / 50000.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn y(&self) -> f32 {
|
||||||
|
self.y as f32 / 50000.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_x(&mut self, x: f32) {
|
||||||
|
self.x = (x * 50000.0) as u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_y(&mut self, y: f32) {
|
||||||
|
self.y = (y * 50000.0) as u16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for VideoMasteringDisplayInfoCoordinate {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("VideoMasteringDisplayInfoCoordinate")
|
||||||
|
.field("x", &self.x())
|
||||||
|
.field("y", &self.y())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue