use ffmpeg_sys_next::*;
use crate::consts::{Const, Mut};
use crate::dict::Dictionary;
use crate::utils::check_i64;
pub struct Streams<'a> {
input: &'a AVFormatContext,
}
unsafe impl Send for Streams<'_> {}
impl<'a> Streams<'a> {
pub(crate) fn new(input: &'a AVFormatContext) -> Self {
Self { input }
}
pub fn best(&self, media_type: AVMediaType) -> Option<Const<'a, Stream<'a>>> {
let stream =
unsafe { av_find_best_stream(self.input as *const _ as *mut _, media_type, -1, -1, std::ptr::null_mut(), 0) };
if stream < 0 {
return None;
}
let stream = unsafe { &mut *(*self.input.streams.add(stream as usize)) };
Some(Const::new(Stream::new(stream, self.input)))
}
pub fn best_mut(&mut self, media_type: AVMediaType) -> Option<Stream<'a>> {
self.best(media_type).map(|s| s.0)
}
}
impl<'a> IntoIterator for Streams<'a> {
type IntoIter = StreamIter<'a>;
type Item = Const<'a, Stream<'a>>;
fn into_iter(self) -> Self::IntoIter {
StreamIter {
input: self.input,
index: 0,
}
}
}
impl<'a> Streams<'a> {
pub fn iter(&'a self) -> StreamIter<'a> {
StreamIter {
input: self.input,
index: 0,
}
}
pub fn len(&self) -> usize {
self.input.nb_streams as usize
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&mut self, index: usize) -> Option<Stream<'_>> {
if index >= self.len() {
return None;
}
let stream = unsafe { &mut *(*self.input.streams.add(index)) };
Some(Stream::new(stream, self.input))
}
}
pub struct StreamIter<'a> {
input: &'a AVFormatContext,
index: usize,
}
impl<'a> Iterator for StreamIter<'a> {
type Item = Const<'a, Stream<'a>>;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.input.nb_streams as usize {
return None;
}
let stream = unsafe { &mut *(*self.input.streams.add(self.index)) };
self.index += 1;
Some(Const::new(Stream::new(stream, self.input)))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.input.nb_streams as usize - self.index;
(remaining, Some(remaining))
}
}
impl std::iter::ExactSizeIterator for StreamIter<'_> {}
pub struct Stream<'a>(&'a mut AVStream, &'a AVFormatContext);
impl<'a> Stream<'a> {
pub(crate) fn new(stream: &'a mut AVStream, input: &'a AVFormatContext) -> Self {
Self(stream, input)
}
pub fn as_ptr(&self) -> *const AVStream {
self.0
}
pub fn as_mut_ptr(&mut self) -> *mut AVStream {
self.0
}
}
impl<'a> Stream<'a> {
pub fn index(&self) -> i32 {
self.0.index
}
pub fn id(&self) -> i32 {
self.0.id
}
pub fn codec_parameters(&self) -> Option<&'a AVCodecParameters> {
unsafe { self.0.codecpar.as_ref() }
}
pub fn time_base(&self) -> AVRational {
self.0.time_base
}
pub fn set_time_base(&mut self, time_base: AVRational) {
self.0.time_base = time_base;
}
pub fn start_time(&self) -> Option<i64> {
check_i64(self.0.start_time)
}
pub fn set_start_time(&mut self, start_time: Option<i64>) {
self.0.start_time = start_time.unwrap_or(AV_NOPTS_VALUE)
}
pub fn duration(&self) -> Option<i64> {
check_i64(self.0.duration)
}
pub fn set_duration(&mut self, duration: Option<i64>) {
self.0.duration = duration.unwrap_or(AV_NOPTS_VALUE)
}
pub fn nb_frames(&self) -> Option<i64> {
check_i64(self.0.nb_frames)
}
pub fn set_nb_frames(&mut self, nb_frames: i64) {
self.0.nb_frames = nb_frames;
}
pub fn disposition(&self) -> i32 {
self.0.disposition
}
pub fn set_disposition(&mut self, disposition: i32) {
self.0.disposition = disposition;
}
pub fn discard(&self) -> AVDiscard {
self.0.discard
}
pub fn set_discard(&mut self, discard: AVDiscard) {
self.0.discard = discard;
}
pub fn sample_aspect_ratio(&self) -> AVRational {
self.0.sample_aspect_ratio
}
pub fn set_sample_aspect_ratio(&mut self, sample_aspect_ratio: AVRational) {
self.0.sample_aspect_ratio = sample_aspect_ratio;
}
pub fn metadata(&self) -> Const<'_, Dictionary> {
Const::new(unsafe { Dictionary::from_ptr_ref(self.0.metadata) })
}
pub fn metadata_mut(&mut self) -> Mut<'_, Dictionary> {
Mut::new(unsafe { Dictionary::from_ptr_ref(self.0.metadata) })
}
pub fn avg_frame_rate(&self) -> AVRational {
self.0.avg_frame_rate
}
pub fn r_frame_rate(&self) -> AVRational {
self.0.r_frame_rate
}
pub fn format_context(&self) -> &'a AVFormatContext {
self.1
}
}
impl std::fmt::Debug for Stream<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Stream")
.field("index", &self.index())
.field("id", &self.id())
.field("time_base", &self.time_base())
.field("start_time", &self.start_time())
.field("duration", &self.duration())
.field("nb_frames", &self.nb_frames())
.field("disposition", &self.disposition())
.field("discard", &self.discard())
.field("sample_aspect_ratio", &self.sample_aspect_ratio())
.field("metadata", &self.metadata())
.field("avg_frame_rate", &self.avg_frame_rate())
.field("r_frame_rate", &self.r_frame_rate())
.finish()
}
}