Skip to main content

ffmpeg_next/format/stream/
stream.rs

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