Skip to content
Commits on Source (10)
......@@ -18,6 +18,9 @@ external_libraries = [
]
generate = [
"GstAudio.AudioDitherMethod",
"GstAudio.AudioNoiseShapingMethod",
"GstAudio.AudioResamplerMethod",
"GstAudio.AudioFormatFlags",
"GstAudio.AudioLayout",
"GstAudio.AudioChannelPosition",
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......
[package]
name = "gstreamer-app"
version = "0.16.6"
version = "0.16.7"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
categories = ["api-bindings", "multimedia"]
description = "Rust bindings for GStreamer App library"
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......
[package]
name = "gstreamer-audio"
version = "0.16.6"
version = "0.16.7"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
categories = ["api-bindings", "multimedia"]
description = "Rust bindings for GStreamer Audio library"
......
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::prelude::*;
use std::convert;
use std::ops;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AudioConverterConfig(gst::Structure);
impl ops::Deref for AudioConverterConfig {
type Target = gst::StructureRef;
fn deref(&self) -> &gst::StructureRef {
self.0.deref()
}
}
impl ops::DerefMut for AudioConverterConfig {
fn deref_mut(&mut self) -> &mut gst::StructureRef {
self.0.deref_mut()
}
}
impl AsRef<gst::StructureRef> for AudioConverterConfig {
fn as_ref(&self) -> &gst::StructureRef {
self.0.as_ref()
}
}
impl AsMut<gst::StructureRef> for AudioConverterConfig {
fn as_mut(&mut self) -> &mut gst::StructureRef {
self.0.as_mut()
}
}
impl Default for AudioConverterConfig {
fn default() -> Self {
AudioConverterConfig::new()
}
}
impl convert::TryFrom<gst::Structure> for AudioConverterConfig {
type Error = glib::BoolError;
fn try_from(v: gst::Structure) -> Result<AudioConverterConfig, Self::Error> {
skip_assert_initialized!();
if v.get_name() == "GstAudioConverter" {
Ok(AudioConverterConfig(v))
} else {
Err(glib_bool_error!("Structure is no AudioConverterConfig"))
}
}
}
impl<'a> convert::TryFrom<&'a gst::StructureRef> for AudioConverterConfig {
type Error = glib::BoolError;
fn try_from(v: &'a gst::StructureRef) -> Result<AudioConverterConfig, Self::Error> {
skip_assert_initialized!();
AudioConverterConfig::try_from(v.to_owned())
}
}
impl From<AudioConverterConfig> for gst::Structure {
fn from(v: AudioConverterConfig) -> gst::Structure {
skip_assert_initialized!();
v.0
}
}
impl AudioConverterConfig {
pub fn new() -> Self {
AudioConverterConfig(gst::Structure::new_empty("GstAudioConverter"))
}
pub fn set_dither_method(&mut self, v: crate::AudioDitherMethod) {
self.0.set("GstAudioConverter.dither-method", &v);
}
pub fn get_dither_method(&self) -> crate::AudioDitherMethod {
self.0
.get_optional("GstAudioConverter.dither-method")
.expect("Wrong type")
.unwrap_or(crate::AudioDitherMethod::None)
}
pub fn set_noise_shaping_method(&mut self, v: crate::AudioNoiseShapingMethod) {
self.0.set("GstAudioConverter.noise-shaping-method", &v);
}
pub fn get_noise_shaping_method(&self) -> crate::AudioNoiseShapingMethod {
self.0
.get_optional("GstAudioConverter.noise-shaping-method")
.expect("Wrong type")
.unwrap_or(crate::AudioNoiseShapingMethod::None)
}
pub fn set_quantization(&mut self, v: u32) {
self.0.set("GstAudioConverter.quantization", &v);
}
pub fn get_quantization(&self) -> u32 {
self.0
.get_optional("GstAudioConverter.quantization")
.expect("Wrong type")
.unwrap_or(1)
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_10")))]
pub fn set_resampler_method(&mut self, v: crate::AudioResamplerMethod) {
self.0.set("GstAudioConverter.resampler-method", &v);
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_10")))]
pub fn get_resampler_method(&self) -> crate::AudioResamplerMethod {
self.0
.get_optional("GstAudioConverter.resampler-method")
.expect("Wrong type")
.unwrap_or(crate::AudioResamplerMethod::BlackmanNuttall)
}
pub fn set_mix_matrix<T: AsRef<[f32]>>(&mut self, v: &[T]) {
let length = v.get(0).map(|v| v.as_ref().len()).unwrap_or(0);
let array = gst::Array::from_owned(
v.iter()
.map(|val| {
let val = val.as_ref();
assert_eq!(val.len(), length);
gst::Array::from_owned(
val.iter()
.map(|val| val.to_send_value())
.collect::<Vec<_>>(),
)
.to_send_value()
})
.collect::<Vec<_>>(),
);
self.0.set("GstAudioConverter.mix-matrix", &array);
}
pub fn get_mix_matrix(&self) -> Vec<Vec<f32>> {
self.0
.get_optional::<gst::Array>("GstAudioConverter.mix-matrix")
.expect("Wrong type")
.map(|array| {
array
.as_slice()
.iter()
.map(|val| {
let array = val
.get::<gst::Array>()
.expect("Wrong type")
.unwrap_or_else(|| gst::Array::from_owned(Vec::new()));
array
.as_slice()
.iter()
.map(|val| val.get_some::<f32>().expect("Wrong type"))
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
})
.unwrap_or_else(Vec::new)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mix_matrix() {
const MATRIX: &[&[f32]] = &[&[1.2, 0.3], &[0.2, 0.8]];
gst::init().unwrap();
let mut config = AudioConverterConfig::new();
config.set_mix_matrix(MATRIX);
let matrix = config.get_mix_matrix();
assert_eq!(matrix, MATRIX);
config.set_mix_matrix(&matrix);
}
}
......@@ -193,6 +193,70 @@ impl SetValue for AudioChannelPosition {
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
pub enum AudioDitherMethod {
None,
Rpdf,
Tpdf,
TpdfHf,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl ToGlib for AudioDitherMethod {
type GlibType = gst_audio_sys::GstAudioDitherMethod;
fn to_glib(&self) -> gst_audio_sys::GstAudioDitherMethod {
match *self {
AudioDitherMethod::None => gst_audio_sys::GST_AUDIO_DITHER_NONE,
AudioDitherMethod::Rpdf => gst_audio_sys::GST_AUDIO_DITHER_RPDF,
AudioDitherMethod::Tpdf => gst_audio_sys::GST_AUDIO_DITHER_TPDF,
AudioDitherMethod::TpdfHf => gst_audio_sys::GST_AUDIO_DITHER_TPDF_HF,
AudioDitherMethod::__Unknown(value) => value,
}
}
}
#[doc(hidden)]
impl FromGlib<gst_audio_sys::GstAudioDitherMethod> for AudioDitherMethod {
fn from_glib(value: gst_audio_sys::GstAudioDitherMethod) -> Self {
skip_assert_initialized!();
match value {
0 => AudioDitherMethod::None,
1 => AudioDitherMethod::Rpdf,
2 => AudioDitherMethod::Tpdf,
3 => AudioDitherMethod::TpdfHf,
value => AudioDitherMethod::__Unknown(value),
}
}
}
impl StaticType for AudioDitherMethod {
fn static_type() -> Type {
unsafe { from_glib(gst_audio_sys::gst_audio_dither_method_get_type()) }
}
}
impl<'a> FromValueOptional<'a> for AudioDitherMethod {
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
Some(FromValue::from_value(value))
}
}
impl<'a> FromValue<'a> for AudioDitherMethod {
unsafe fn from_value(value: &Value) -> Self {
from_glib(gobject_sys::g_value_get_enum(value.to_glib_none().0))
}
}
impl SetValue for AudioDitherMethod {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_sys::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib())
}
}
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
#[non_exhaustive]
pub enum AudioFormat {
......@@ -399,6 +463,151 @@ impl SetValue for AudioLayout {
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
pub enum AudioNoiseShapingMethod {
None,
ErrorFeedback,
Simple,
Medium,
High,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl ToGlib for AudioNoiseShapingMethod {
type GlibType = gst_audio_sys::GstAudioNoiseShapingMethod;
fn to_glib(&self) -> gst_audio_sys::GstAudioNoiseShapingMethod {
match *self {
AudioNoiseShapingMethod::None => gst_audio_sys::GST_AUDIO_NOISE_SHAPING_NONE,
AudioNoiseShapingMethod::ErrorFeedback => {
gst_audio_sys::GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK
}
AudioNoiseShapingMethod::Simple => gst_audio_sys::GST_AUDIO_NOISE_SHAPING_SIMPLE,
AudioNoiseShapingMethod::Medium => gst_audio_sys::GST_AUDIO_NOISE_SHAPING_MEDIUM,
AudioNoiseShapingMethod::High => gst_audio_sys::GST_AUDIO_NOISE_SHAPING_HIGH,
AudioNoiseShapingMethod::__Unknown(value) => value,
}
}
}
#[doc(hidden)]
impl FromGlib<gst_audio_sys::GstAudioNoiseShapingMethod> for AudioNoiseShapingMethod {
fn from_glib(value: gst_audio_sys::GstAudioNoiseShapingMethod) -> Self {
skip_assert_initialized!();
match value {
0 => AudioNoiseShapingMethod::None,
1 => AudioNoiseShapingMethod::ErrorFeedback,
2 => AudioNoiseShapingMethod::Simple,
3 => AudioNoiseShapingMethod::Medium,
4 => AudioNoiseShapingMethod::High,
value => AudioNoiseShapingMethod::__Unknown(value),
}
}
}
impl StaticType for AudioNoiseShapingMethod {
fn static_type() -> Type {
unsafe { from_glib(gst_audio_sys::gst_audio_noise_shaping_method_get_type()) }
}
}
impl<'a> FromValueOptional<'a> for AudioNoiseShapingMethod {
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
Some(FromValue::from_value(value))
}
}
impl<'a> FromValue<'a> for AudioNoiseShapingMethod {
unsafe fn from_value(value: &Value) -> Self {
from_glib(gobject_sys::g_value_get_enum(value.to_glib_none().0))
}
}
impl SetValue for AudioNoiseShapingMethod {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_sys::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib())
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
pub enum AudioResamplerMethod {
Nearest,
Linear,
Cubic,
BlackmanNuttall,
Kaiser,
#[doc(hidden)]
__Unknown(i32),
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
#[doc(hidden)]
impl ToGlib for AudioResamplerMethod {
type GlibType = gst_audio_sys::GstAudioResamplerMethod;
fn to_glib(&self) -> gst_audio_sys::GstAudioResamplerMethod {
match *self {
AudioResamplerMethod::Nearest => gst_audio_sys::GST_AUDIO_RESAMPLER_METHOD_NEAREST,
AudioResamplerMethod::Linear => gst_audio_sys::GST_AUDIO_RESAMPLER_METHOD_LINEAR,
AudioResamplerMethod::Cubic => gst_audio_sys::GST_AUDIO_RESAMPLER_METHOD_CUBIC,
AudioResamplerMethod::BlackmanNuttall => {
gst_audio_sys::GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL
}
AudioResamplerMethod::Kaiser => gst_audio_sys::GST_AUDIO_RESAMPLER_METHOD_KAISER,
AudioResamplerMethod::__Unknown(value) => value,
}
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
#[doc(hidden)]
impl FromGlib<gst_audio_sys::GstAudioResamplerMethod> for AudioResamplerMethod {
fn from_glib(value: gst_audio_sys::GstAudioResamplerMethod) -> Self {
skip_assert_initialized!();
match value {
0 => AudioResamplerMethod::Nearest,
1 => AudioResamplerMethod::Linear,
2 => AudioResamplerMethod::Cubic,
3 => AudioResamplerMethod::BlackmanNuttall,
4 => AudioResamplerMethod::Kaiser,
value => AudioResamplerMethod::__Unknown(value),
}
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
impl StaticType for AudioResamplerMethod {
fn static_type() -> Type {
unsafe { from_glib(gst_audio_sys::gst_audio_resampler_method_get_type()) }
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
impl<'a> FromValueOptional<'a> for AudioResamplerMethod {
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
Some(FromValue::from_value(value))
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
impl<'a> FromValue<'a> for AudioResamplerMethod {
unsafe fn from_value(value: &Value) -> Self {
from_glib(gobject_sys::g_value_get_enum(value.to_glib_none().0))
}
}
#[cfg(any(feature = "v1_10", feature = "dox"))]
impl SetValue for AudioResamplerMethod {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_sys::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib())
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
pub enum AudioRingBufferFormatType {
......
......@@ -35,8 +35,12 @@ pub use self::audio_stream_align::AudioStreamAlign;
mod enums;
pub use self::enums::AudioChannelPosition;
pub use self::enums::AudioDitherMethod;
pub use self::enums::AudioFormat;
pub use self::enums::AudioLayout;
pub use self::enums::AudioNoiseShapingMethod;
#[cfg(any(feature = "v1_10", feature = "dox"))]
pub use self::enums::AudioResamplerMethod;
pub use self::enums::AudioRingBufferFormatType;
pub use self::enums::StreamVolumeFormat;
......
......@@ -69,6 +69,9 @@ pub use audio_decoder::AudioDecoderExtManual;
mod audio_encoder;
pub use audio_encoder::AudioEncoderExtManual;
mod audio_converter;
pub use crate::audio_converter::AudioConverterConfig;
// Re-export all the traits in a prelude module, so that applications
// can always "use gst::prelude::*" without getting conflicts
pub mod prelude {
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......
[package]
name = "gstreamer-base"
version = "0.16.6"
version = "0.16.7"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
categories = ["api-bindings", "multimedia"]
description = "Rust bindings for GStreamer Base library"
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......
[package]
name = "gstreamer-check"
version = "0.16.6"
version = "0.16.7"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
categories = ["api-bindings", "multimedia"]
description = "Rust bindings for GStreamer Check library"
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......
[package]
name = "gstreamer-editing-services"
version = "0.16.6"
version = "0.16.7"
authors = ["Thibault Saunier <tsaunier@igalia.com>", "Sebastian Dröge <sebastian@centricular.com>"]
categories = ["api-bindings", "multimedia"]
description = "Rust bindings for GStreamer Editing Services"
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......
[package]
name = "gstreamer-gl"
version = "0.16.6"
version = "0.16.7"
authors = ["Sebastian Dröge <sebastian@centricular.com>",
"Víctor M. Jáquez L. <vjaquez@igalia.com>"]
categories = ["api-bindings", "multimedia"]
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......
[package]
name = "gstreamer-net"
version = "0.16.6"
version = "0.16.7"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
categories = ["api-bindings", "multimedia"]
description = "Rust bindings for GStreamer Net library"
......
......@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.16.7] - 2021-02-13
### Fixed
- Usage of the logging system with a GStreamer library with the logging system
compiled out does not crash any longer.
- Double-free in `gst_video::VideoTimeCode` API when converting between
validated and unvalidated timecodes.
### Added
- `gst::Element::get_current_state()` and `get_pending_state()` convenience APIs.
- `gst_audio::AudioConverterConfig` for setting the configuration on e.g. the
`audiomixer` element. The low-level `AudioConverter` API is still not
included in the bindings.
## [0.16.6] - 2020-12-20
### Fixed
- `VideoTimeCodeInterval`'s `Ord` and `PartialEq` implementations compare
......