playa_ffmpeg/format/context/
input.rs1use std::{
2 ffi::CString,
3 mem,
4 ops::{Deref, DerefMut},
5};
6
7use super::{common::Context, destructor};
8#[cfg(not(feature = "ffmpeg_5_0"))]
9use crate::Codec;
10use crate::{Error, Packet, Stream, ffi::*, format, util::range::Range};
11
12pub struct Input {
13 ptr: *mut AVFormatContext,
14 ctx: Context,
15}
16
17unsafe impl Send for Input {}
18
19impl Input {
20 pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
21 Input { ptr, ctx: unsafe { Context::wrap(ptr, destructor::Mode::Input) } }
22 }
23
24 pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
25 self.ptr as *const _
26 }
27
28 pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
29 self.ptr
30 }
31}
32
33impl Input {
34 pub fn format(&self) -> format::Input {
35 #[allow(clippy::unnecessary_cast)]
37 unsafe {
38 format::Input::wrap((*self.as_ptr()).iformat as *mut AVInputFormat)
39 }
40 }
41
42 #[cfg(not(feature = "ffmpeg_5_0"))]
43 pub fn video_codec(&self) -> Option<Codec> {
44 unsafe {
45 let ptr = (*self.as_ptr()).video_codec;
46
47 if ptr.is_null() { None } else { Some(Codec::wrap(ptr)) }
48 }
49 }
50
51 #[cfg(not(feature = "ffmpeg_5_0"))]
52 pub fn audio_codec(&self) -> Option<Codec> {
53 unsafe {
54 let ptr = (*self.as_ptr()).audio_codec;
55
56 if ptr.is_null() { None } else { Some(Codec::wrap(ptr)) }
57 }
58 }
59
60 #[cfg(not(feature = "ffmpeg_5_0"))]
61 pub fn subtitle_codec(&self) -> Option<Codec> {
62 unsafe {
63 let ptr = (*self.as_ptr()).subtitle_codec;
64
65 if ptr.is_null() { None } else { Some(Codec::wrap(ptr)) }
66 }
67 }
68
69 #[cfg(not(feature = "ffmpeg_5_0"))]
70 pub fn data_codec(&self) -> Option<Codec> {
71 unsafe {
72 let ptr = (*self.as_ptr()).data_codec;
73
74 if ptr.is_null() { None } else { Some(Codec::wrap(ptr)) }
75 }
76 }
77
78 pub fn probe_score(&self) -> i32 {
79 unsafe { (*self.as_ptr()).probe_score }
80 }
81
82 pub fn packets(&mut self) -> PacketIter<'_> {
83 PacketIter::new(self)
84 }
85
86 pub fn pause(&mut self) -> Result<(), Error> {
87 unsafe {
88 match av_read_pause(self.as_mut_ptr()) {
89 0 => Ok(()),
90 e => Err(Error::from(e)),
91 }
92 }
93 }
94
95 pub fn play(&mut self) -> Result<(), Error> {
96 unsafe {
97 match av_read_play(self.as_mut_ptr()) {
98 0 => Ok(()),
99 e => Err(Error::from(e)),
100 }
101 }
102 }
103
104 pub fn seek<R: Range<i64>>(&mut self, ts: i64, range: R) -> Result<(), Error> {
105 unsafe {
106 match avformat_seek_file(self.as_mut_ptr(), -1, range.start().cloned().unwrap_or(i64::MIN), ts, range.end().cloned().unwrap_or(i64::MAX), 0) {
107 s if s >= 0 => Ok(()),
108 e => Err(Error::from(e)),
109 }
110 }
111 }
112}
113
114impl Deref for Input {
115 type Target = Context;
116
117 fn deref(&self) -> &Self::Target {
118 &self.ctx
119 }
120}
121
122impl DerefMut for Input {
123 fn deref_mut(&mut self) -> &mut Self::Target {
124 &mut self.ctx
125 }
126}
127
128pub struct PacketIter<'a> {
129 context: &'a mut Input,
130}
131
132impl<'a> PacketIter<'a> {
133 pub fn new(context: &mut Input) -> PacketIter<'_> {
134 PacketIter { context }
135 }
136}
137
138impl<'a> Iterator for PacketIter<'a> {
139 type Item = (Stream<'a>, Packet);
140
141 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
142 let mut packet = Packet::empty();
143
144 loop {
145 match packet.read(self.context) {
146 Ok(..) => unsafe {
147 return Some((Stream::wrap(mem::transmute_copy(&self.context), packet.stream()), packet));
148 },
149
150 Err(Error::Eof) => return None,
151
152 Err(..) => (),
153 }
154 }
155 }
156}
157
158pub fn dump(ctx: &Input, index: i32, url: Option<&str>) {
159 let url = url.map(|u| CString::new(u).unwrap());
160
161 unsafe {
162 av_dump_format(ctx.as_ptr() as *mut _, index, url.unwrap_or_else(|| CString::new("").unwrap()).as_ptr(), 0);
163 }
164}