ffmpeg_the_third/format/stream/
stream.rs1use 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 pub fn sample_aspect_ratio(&self) -> Rational {
90 unsafe { Rational::from((*self.as_ptr()).sample_aspect_ratio) }
91 }
92}
93
94impl<'a> PartialEq for Stream<'a> {
95 fn eq(&self, other: &Self) -> bool {
96 unsafe { self.as_ptr() == other.as_ptr() }
97 }
98}
99
100impl<'a> Eq for Stream<'a> {}
101
102#[cfg(not(feature = "ffmpeg_8_0"))]
103pub struct SideDataIter<'a> {
104 stream: &'a Stream<'a>,
105 current: c_int,
106}
107
108#[cfg(not(feature = "ffmpeg_8_0"))]
109impl<'a> SideDataIter<'a> {
110 pub fn new<'sd, 's: 'sd>(stream: &'s Stream) -> SideDataIter<'sd> {
111 SideDataIter { stream, current: 0 }
112 }
113}
114
115#[cfg(not(feature = "ffmpeg_8_0"))]
116impl<'a> Iterator for SideDataIter<'a> {
117 type Item = packet::SideData<'a>;
118
119 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
120 unsafe {
121 if self.current >= (*self.stream.as_ptr()).nb_side_data {
122 return None;
123 }
124
125 self.current += 1;
126
127 Some(packet::SideData::wrap(
128 (*self.stream.as_ptr())
129 .side_data
130 .offset((self.current - 1) as isize),
131 ))
132 }
133 }
134
135 fn size_hint(&self) -> (usize, Option<usize>) {
136 unsafe {
137 let length = (*self.stream.as_ptr()).nb_side_data as usize;
138
139 (
140 length - self.current as usize,
141 Some(length - self.current as usize),
142 )
143 }
144 }
145}
146
147#[cfg(not(feature = "ffmpeg_8_0"))]
148impl<'a> ExactSizeIterator for SideDataIter<'a> {}