ffmpeg_the_third/format/stream/
stream.rs

1use super::Disposition;
2use crate::codec;
3use crate::ffi::*;
4use crate::format::context::common::Context;
5use crate::{DictionaryRef, Discard, Rational};
6
7#[cfg(not(feature = "ffmpeg_8_0"))]
8use crate::codec::packet;
9#[cfg(not(feature = "ffmpeg_8_0"))]
10use libc::c_int;
11
12#[derive(Debug)]
13pub struct Stream<'a> {
14    context: &'a Context,
15    index: usize,
16}
17
18impl<'a> Stream<'a> {
19    pub unsafe fn wrap(context: &Context, index: usize) -> Stream<'_> {
20        Stream { context, index }
21    }
22
23    pub unsafe fn as_ptr(&self) -> *const AVStream {
24        *(*self.context.as_ptr()).streams.add(self.index)
25    }
26}
27
28impl<'a> Stream<'a> {
29    pub fn id(&self) -> i32 {
30        unsafe { (*self.as_ptr()).id }
31    }
32
33    #[cfg(not(feature = "ffmpeg_5_0"))]
34    pub fn codec(&self) -> codec::Context {
35        unsafe { codec::Context::wrap((*self.as_ptr()).codec, Some(self.context.destructor())) }
36    }
37
38    pub fn parameters(&self) -> codec::ParametersRef<'_> {
39        unsafe {
40            codec::ParametersRef::from_raw((*self.as_ptr()).codecpar).expect("codecpar is non-null")
41        }
42    }
43
44    pub fn index(&self) -> usize {
45        unsafe { (*self.as_ptr()).index as usize }
46    }
47
48    pub fn time_base(&self) -> Rational {
49        unsafe { Rational::from((*self.as_ptr()).time_base) }
50    }
51
52    pub fn start_time(&self) -> i64 {
53        unsafe { (*self.as_ptr()).start_time }
54    }
55
56    pub fn duration(&self) -> i64 {
57        unsafe { (*self.as_ptr()).duration }
58    }
59
60    pub fn frames(&self) -> i64 {
61        unsafe { (*self.as_ptr()).nb_frames }
62    }
63
64    pub fn disposition(&self) -> Disposition {
65        unsafe { Disposition::from_bits_truncate((*self.as_ptr()).disposition) }
66    }
67
68    pub fn discard(&self) -> Discard {
69        unsafe { Discard::from((*self.as_ptr()).discard) }
70    }
71
72    #[cfg(not(feature = "ffmpeg_8_0"))]
73    pub fn side_data(&self) -> SideDataIter<'_> {
74        SideDataIter::new(self)
75    }
76
77    pub fn rate(&self) -> Rational {
78        unsafe { Rational::from((*self.as_ptr()).r_frame_rate) }
79    }
80
81    pub fn avg_frame_rate(&self) -> Rational {
82        unsafe { Rational::from((*self.as_ptr()).avg_frame_rate) }
83    }
84
85    pub fn metadata(&self) -> DictionaryRef<'_> {
86        unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
87    }
88}
89
90impl<'a> PartialEq for Stream<'a> {
91    fn eq(&self, other: &Self) -> bool {
92        unsafe { self.as_ptr() == other.as_ptr() }
93    }
94}
95
96impl<'a> Eq for Stream<'a> {}
97
98#[cfg(not(feature = "ffmpeg_8_0"))]
99pub struct SideDataIter<'a> {
100    stream: &'a Stream<'a>,
101    current: c_int,
102}
103
104#[cfg(not(feature = "ffmpeg_8_0"))]
105impl<'a> SideDataIter<'a> {
106    pub fn new<'sd, 's: 'sd>(stream: &'s Stream) -> SideDataIter<'sd> {
107        SideDataIter { stream, current: 0 }
108    }
109}
110
111#[cfg(not(feature = "ffmpeg_8_0"))]
112impl<'a> Iterator for SideDataIter<'a> {
113    type Item = packet::SideData<'a>;
114
115    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
116        unsafe {
117            if self.current >= (*self.stream.as_ptr()).nb_side_data {
118                return None;
119            }
120
121            self.current += 1;
122
123            Some(packet::SideData::wrap(
124                (*self.stream.as_ptr())
125                    .side_data
126                    .offset((self.current - 1) as isize),
127            ))
128        }
129    }
130
131    fn size_hint(&self) -> (usize, Option<usize>) {
132        unsafe {
133            let length = (*self.stream.as_ptr()).nb_side_data as usize;
134
135            (
136                length - self.current as usize,
137                Some(length - self.current as usize),
138            )
139        }
140    }
141}
142
143#[cfg(not(feature = "ffmpeg_8_0"))]
144impl<'a> ExactSizeIterator for SideDataIter<'a> {}