playa_ffmpeg/format/stream/
stream.rs1use super::Disposition;
2use crate::{
3 DictionaryRef, Discard, Rational,
4 codec::{self, packet},
5 ffi::*,
6 format::context::common::Context,
7};
8use libc::c_int;
9
10#[derive(Debug)]
11pub struct Stream<'a> {
12 context: &'a Context,
13 index: usize,
14}
15
16impl<'a> Stream<'a> {
17 pub unsafe fn wrap(context: &Context, index: usize) -> Stream<'_> {
18 Stream { context, index }
19 }
20
21 pub unsafe fn as_ptr(&self) -> *const AVStream {
22 unsafe { *(*self.context.as_ptr()).streams.add(self.index) }
23 }
24}
25
26impl<'a> Stream<'a> {
27 pub fn id(&self) -> i32 {
28 unsafe { (*self.as_ptr()).id }
29 }
30
31 #[cfg(not(feature = "ffmpeg_5_0"))]
32 pub fn codec(&self) -> codec::Context {
33 unsafe { codec::Context::wrap((*self.as_ptr()).codec, Some(self.context.destructor())) }
34 }
35
36 pub fn parameters(&self) -> codec::Parameters {
37 unsafe { codec::Parameters::wrap((*self.as_ptr()).codecpar, Some(self.context.destructor())) }
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((*self.stream.as_ptr()).side_data.offset((self.current - 1) as isize)))
117 }
118 #[cfg(feature = "ffmpeg_8_0")]
119 unsafe {
120 if self.current >= (*self.stream.parameters().as_ptr()).nb_coded_side_data {
121 return None;
122 }
123
124 self.current += 1;
125
126 Some(packet::SideData::wrap((*self.stream.parameters().as_ptr()).coded_side_data.offset((self.current - 1) as isize) as *mut _))
127 }
128 }
129
130 fn size_hint(&self) -> (usize, Option<usize>) {
131 unsafe {
132 #[cfg(not(feature = "ffmpeg_8_0"))]
133 let length = (*self.stream.as_ptr()).nb_side_data as usize;
134 #[cfg(feature = "ffmpeg_8_0")]
135 let length = (*self.stream.parameters().as_ptr()).nb_coded_side_data as usize;
136
137 (length - self.current as usize, Some(length - self.current as usize))
138 }
139 }
140}
141
142impl<'a> ExactSizeIterator for SideDataIter<'a> {}