1use crate::codec::DecoderCodec;
2use crate::error::{FfmpegError, FfmpegErrorCode};
3use crate::ffi::*;
4use crate::frame::{AudioFrame, GenericFrame, VideoFrame};
5use crate::packet::Packet;
6use crate::rational::Rational;
7use crate::smart_object::SmartPtr;
8use crate::stream::Stream;
9use crate::{AVCodecID, AVMediaType, AVPixelFormat, AVSampleFormat};
10
11#[derive(Debug)]
15pub enum Decoder {
16 Video(VideoDecoder),
18 Audio(AudioDecoder),
20}
21
22pub struct GenericDecoder {
24 decoder: SmartPtr<AVCodecContext>,
25}
26
27unsafe impl Send for GenericDecoder {}
29
30impl std::fmt::Debug for GenericDecoder {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 f.debug_struct("Decoder")
33 .field("time_base", &self.time_base())
34 .field("codec_type", &self.codec_type())
35 .finish()
36 }
37}
38
39pub struct VideoDecoder(GenericDecoder);
41
42impl std::fmt::Debug for VideoDecoder {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 f.debug_struct("VideoDecoder")
45 .field("time_base", &self.time_base())
46 .field("width", &self.width())
47 .field("height", &self.height())
48 .field("pixel_format", &self.pixel_format())
49 .field("frame_rate", &self.frame_rate())
50 .field("sample_aspect_ratio", &self.sample_aspect_ratio())
51 .finish()
52 }
53}
54
55pub struct AudioDecoder(GenericDecoder);
57
58impl std::fmt::Debug for AudioDecoder {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 f.debug_struct("AudioDecoder")
61 .field("time_base", &self.time_base())
62 .field("sample_rate", &self.sample_rate())
63 .field("channels", &self.channels())
64 .field("sample_fmt", &self.sample_format())
65 .finish()
66 }
67}
68
69pub struct DecoderOptions {
71 pub codec: Option<DecoderCodec>,
73 pub thread_count: i32,
75}
76
77impl Default for DecoderOptions {
79 fn default() -> Self {
80 Self {
81 codec: None,
82 thread_count: 1,
83 }
84 }
85}
86
87impl Decoder {
88 pub fn new(ist: &Stream) -> Result<Self, FfmpegError> {
90 Self::with_options(ist, Default::default())
91 }
92
93 pub fn with_options(ist: &Stream, options: DecoderOptions) -> Result<Self, FfmpegError> {
95 let Some(codec_params) = ist.codec_parameters() else {
96 return Err(FfmpegError::NoDecoder);
97 };
98
99 let codec = options
100 .codec
101 .or_else(|| DecoderCodec::new(AVCodecID(codec_params.codec_id as i32)))
102 .ok_or(FfmpegError::NoDecoder)?;
103
104 if codec.is_empty() {
105 return Err(FfmpegError::NoDecoder);
106 }
107
108 let decoder = unsafe { avcodec_alloc_context3(codec.as_ptr()) };
110
111 let destructor = |ptr: &mut *mut AVCodecContext| {
112 unsafe { avcodec_free_context(ptr) };
114 };
115
116 let mut decoder = unsafe { SmartPtr::wrap_non_null(decoder, destructor) }.ok_or(FfmpegError::Alloc)?;
118
119 FfmpegErrorCode(unsafe { avcodec_parameters_to_context(decoder.as_mut_ptr(), codec_params) }).result()?;
121
122 let decoder_mut = decoder.as_deref_mut_except();
123
124 decoder_mut.pkt_timebase = ist.time_base().into();
125 decoder_mut.time_base = ist.time_base().into();
126 decoder_mut.thread_count = options.thread_count;
127
128 if AVMediaType(decoder_mut.codec_type) == AVMediaType::Video {
129 let format_context = unsafe { ist.format_context() };
135
136 decoder_mut.framerate =
137 unsafe { av_guess_frame_rate(format_context, ist.as_ptr() as *mut AVStream, std::ptr::null_mut()) };
139 }
140
141 if matches!(AVMediaType(decoder_mut.codec_type), AVMediaType::Video | AVMediaType::Audio) {
142 FfmpegErrorCode(unsafe { avcodec_open2(decoder_mut, codec.as_ptr(), std::ptr::null_mut()) }).result()?;
144 }
145
146 Ok(match AVMediaType(decoder_mut.codec_type) {
147 AVMediaType::Video => Self::Video(VideoDecoder(GenericDecoder { decoder })),
148 AVMediaType::Audio => Self::Audio(AudioDecoder(GenericDecoder { decoder })),
149 _ => Err(FfmpegError::NoDecoder)?,
150 })
151 }
152
153 pub fn video(self) -> Result<VideoDecoder, Self> {
155 match self {
156 Self::Video(video) => Ok(video),
157 _ => Err(self),
158 }
159 }
160
161 pub fn audio(self) -> Result<AudioDecoder, Self> {
163 match self {
164 Self::Audio(audio) => Ok(audio),
165 _ => Err(self),
166 }
167 }
168}
169
170impl GenericDecoder {
171 pub const fn codec_type(&self) -> AVMediaType {
173 AVMediaType(self.decoder.as_deref_except().codec_type)
174 }
175
176 pub const fn time_base(&self) -> AVRational {
178 self.decoder.as_deref_except().time_base
179 }
180
181 pub fn send_packet(&mut self, packet: &Packet) -> Result<(), FfmpegError> {
183 FfmpegErrorCode(unsafe { avcodec_send_packet(self.decoder.as_mut_ptr(), packet.as_ptr()) }).result()?;
185 Ok(())
186 }
187
188 pub fn send_eof(&mut self) -> Result<(), FfmpegError> {
190 FfmpegErrorCode(unsafe { avcodec_send_packet(self.decoder.as_mut_ptr(), std::ptr::null()) }).result()?;
192 Ok(())
193 }
194
195 pub fn receive_frame(&mut self) -> Result<Option<GenericFrame>, FfmpegError> {
197 let mut frame = GenericFrame::new()?;
198
199 let ret = FfmpegErrorCode(unsafe { avcodec_receive_frame(self.decoder.as_mut_ptr(), frame.as_mut_ptr()) });
201
202 match ret {
203 FfmpegErrorCode::Eagain | FfmpegErrorCode::Eof => Ok(None),
204 code if code.is_success() => {
205 frame.set_time_base(self.decoder.as_deref_except().time_base);
206 Ok(Some(frame))
207 }
208 code => Err(FfmpegError::Code(code)),
209 }
210 }
211}
212
213impl VideoDecoder {
214 pub const fn width(&self) -> i32 {
216 self.0.decoder.as_deref_except().width
217 }
218
219 pub const fn height(&self) -> i32 {
221 self.0.decoder.as_deref_except().height
222 }
223
224 pub const fn pixel_format(&self) -> AVPixelFormat {
226 AVPixelFormat(self.0.decoder.as_deref_except().pix_fmt)
227 }
228
229 pub fn frame_rate(&self) -> Rational {
231 self.0.decoder.as_deref_except().framerate.into()
232 }
233
234 pub fn sample_aspect_ratio(&self) -> Rational {
236 self.0.decoder.as_deref_except().sample_aspect_ratio.into()
237 }
238
239 pub fn receive_frame(&mut self) -> Result<Option<VideoFrame>, FfmpegError> {
241 Ok(self.0.receive_frame()?.map(|frame| frame.video()))
242 }
243}
244
245impl std::ops::Deref for VideoDecoder {
246 type Target = GenericDecoder;
247
248 fn deref(&self) -> &Self::Target {
249 &self.0
250 }
251}
252
253impl std::ops::DerefMut for VideoDecoder {
254 fn deref_mut(&mut self) -> &mut Self::Target {
255 &mut self.0
256 }
257}
258
259impl AudioDecoder {
260 pub const fn sample_rate(&self) -> i32 {
262 self.0.decoder.as_deref_except().sample_rate
263 }
264
265 pub const fn channels(&self) -> i32 {
267 self.0.decoder.as_deref_except().ch_layout.nb_channels
268 }
269
270 pub const fn sample_format(&self) -> AVSampleFormat {
272 AVSampleFormat(self.0.decoder.as_deref_except().sample_fmt)
273 }
274
275 pub fn receive_frame(&mut self) -> Result<Option<AudioFrame>, FfmpegError> {
277 Ok(self.0.receive_frame()?.map(|frame| frame.audio()))
278 }
279}
280
281impl std::ops::Deref for AudioDecoder {
282 type Target = GenericDecoder;
283
284 fn deref(&self) -> &Self::Target {
285 &self.0
286 }
287}
288
289impl std::ops::DerefMut for AudioDecoder {
290 fn deref_mut(&mut self) -> &mut Self::Target {
291 &mut self.0
292 }
293}
294
295#[cfg(test)]
296#[cfg_attr(all(test, coverage_nightly), coverage(off))]
297mod tests {
298 use crate::codec::DecoderCodec;
299 use crate::decoder::{Decoder, DecoderOptions};
300 use crate::io::Input;
301 use crate::{AVCodecID, AVMediaType};
302
303 #[test]
304 fn test_generic_decoder_debug() {
305 let valid_file_path = "../../assets/avc_aac_large.mp4";
306 let input = Input::open(valid_file_path).expect("Failed to open valid file");
307 let streams = input.streams();
308 let stream = streams
309 .iter()
310 .find(|s| {
311 s.codec_parameters()
312 .map(|p| AVMediaType(p.codec_type) == AVMediaType::Video)
313 .unwrap_or(false)
314 })
315 .expect("No video stream found");
316 let codec_params = stream.codec_parameters().expect("Missing codec parameters");
317 assert_eq!(
318 AVMediaType(codec_params.codec_type),
319 AVMediaType::Video,
320 "Expected the stream to be a video stream"
321 );
322 let decoder_options = DecoderOptions {
323 codec: Some(DecoderCodec::new(AVCodecID::H264).expect("Failed to find H264 codec")),
324 thread_count: 2,
325 };
326 let decoder = Decoder::with_options(&stream, decoder_options).expect("Failed to create Decoder");
327 let generic_decoder = match decoder {
328 Decoder::Video(video_decoder) => video_decoder.0,
329 Decoder::Audio(audio_decoder) => audio_decoder.0,
330 };
331
332 insta::assert_debug_snapshot!(generic_decoder, @r"
333 Decoder {
334 time_base: AVRational {
335 num: 1,
336 den: 15360,
337 },
338 codec_type: AVMediaType::Video,
339 }
340 ");
341 }
342
343 #[test]
344 fn test_video_decoder_debug() {
345 let valid_file_path = "../../assets/avc_aac_large.mp4";
346 let input = Input::open(valid_file_path).expect("Failed to open valid file");
347 let streams = input.streams();
348 let stream = streams
349 .iter()
350 .find(|s| {
351 s.codec_parameters()
352 .map(|p| AVMediaType(p.codec_type) == AVMediaType::Video)
353 .unwrap_or(false)
354 })
355 .expect("No video stream found");
356 let codec_params = stream.codec_parameters().expect("Missing codec parameters");
357 assert_eq!(
358 AVMediaType(codec_params.codec_type),
359 AVMediaType::Video,
360 "Expected the stream to be a video stream"
361 );
362
363 let decoder_options = DecoderOptions {
364 codec: Some(DecoderCodec::new(AVCodecID::H264).expect("Failed to find H264 codec")),
365 thread_count: 2,
366 };
367 let decoder = Decoder::with_options(&stream, decoder_options).expect("Failed to create Decoder");
368
369 let generic_decoder = match decoder {
370 Decoder::Video(video_decoder) => video_decoder,
371 _ => panic!("Expected a video decoder, got something else"),
372 };
373
374 insta::assert_debug_snapshot!(generic_decoder, @r"
375 VideoDecoder {
376 time_base: AVRational {
377 num: 1,
378 den: 15360,
379 },
380 width: 3840,
381 height: 2160,
382 pixel_format: AVPixelFormat::Yuv420p,
383 frame_rate: Rational {
384 numerator: 60,
385 denominator: 1,
386 },
387 sample_aspect_ratio: Rational {
388 numerator: 1,
389 denominator: 1,
390 },
391 }
392 ");
393 }
394
395 #[test]
396 fn test_audio_decoder_debug() {
397 let valid_file_path = "../../assets/avc_aac_large.mp4";
398 let input = Input::open(valid_file_path).expect("Failed to open valid file");
399 let streams = input.streams();
400 let stream = streams
401 .iter()
402 .find(|s| {
403 s.codec_parameters()
404 .map(|p| AVMediaType(p.codec_type) == AVMediaType::Audio)
405 .unwrap_or(false)
406 })
407 .expect("No audio stream found");
408 let codec_params = stream.codec_parameters().expect("Missing codec parameters");
409 assert_eq!(
410 AVMediaType(codec_params.codec_type),
411 AVMediaType::Audio,
412 "Expected the stream to be an audio stream"
413 );
414 let decoder_options = DecoderOptions {
415 codec: Some(DecoderCodec::new(AVCodecID::Aac).expect("Failed to find AAC codec")),
416 thread_count: 2,
417 };
418 let decoder = Decoder::with_options(&stream, decoder_options).expect("Failed to create Decoder");
419 let audio_decoder = match decoder {
420 Decoder::Audio(audio_decoder) => audio_decoder,
421 _ => panic!("Expected an audio decoder, got something else"),
422 };
423
424 insta::assert_debug_snapshot!(audio_decoder, @r"
425 AudioDecoder {
426 time_base: AVRational {
427 num: 1,
428 den: 48000,
429 },
430 sample_rate: 48000,
431 channels: 2,
432 sample_fmt: AVSampleFormat::Fltp,
433 }
434 ");
435 }
436
437 #[test]
438 fn test_decoder_options_default() {
439 let default_options = DecoderOptions::default();
440
441 assert!(default_options.codec.is_none(), "Expected default codec to be None");
442 assert_eq!(default_options.thread_count, 1, "Expected default thread_count to be 1");
443 }
444
445 #[test]
446 fn test_decoder_new() {
447 let valid_file_path = "../../assets/avc_aac_large.mp4";
448 let input = Input::open(valid_file_path).expect("Failed to open valid file");
449 let streams = input.streams();
450 let stream = streams
451 .iter()
452 .find(|s| {
453 s.codec_parameters()
454 .map(|p| AVMediaType(p.codec_type) == AVMediaType::Video)
455 .unwrap_or(false)
456 })
457 .expect("No video stream found");
458
459 let decoder_result = Decoder::new(&stream);
460 assert!(decoder_result.is_ok(), "Expected Decoder::new to succeed, but it failed");
461
462 let decoder = decoder_result.unwrap();
463 if let Decoder::Video(video_decoder) = decoder {
464 assert_eq!(video_decoder.width(), 3840, "Expected valid width for video stream");
465 assert_eq!(video_decoder.height(), 2160, "Expected valid height for video stream");
466 } else {
467 panic!("Expected a video decoder, but got a different type");
468 }
469 }
470
471 #[test]
472 fn test_decoder_with_options_missing_codec_parameters() {
473 let valid_file_path = "../../assets/avc_aac_large.mp4";
474 let mut input = Input::open(valid_file_path).expect("Failed to open valid file");
475 let mut streams = input.streams_mut();
476 let mut stream = streams.get(0).expect("Expected a valid stream");
477 let codecpar = unsafe { (*stream.as_mut_ptr()).codecpar };
479 unsafe {
481 (*stream.as_mut_ptr()).codecpar = std::ptr::null_mut();
482 }
483 let decoder_result = Decoder::with_options(&stream, DecoderOptions::default());
484 unsafe {
486 (*stream.as_mut_ptr()).codecpar = codecpar;
487 }
488
489 assert!(decoder_result.is_err(), "Expected Decoder creation to fail");
490 if let Err(err) = decoder_result {
491 match err {
492 crate::error::FfmpegError::NoDecoder => (),
493 _ => panic!("Unexpected error type: {:?}", err),
494 }
495 }
496 }
497
498 #[test]
499 fn test_decoder_with_options_non_video_audio_codec_type() {
500 let valid_file_path = "../../assets/avc_aac_large.mp4";
501 let mut input = Input::open(valid_file_path).expect("Failed to open valid file");
502 let mut streams = input.streams_mut();
503 let mut stream = streams.get(0).expect("Expected a valid stream");
504 let codecpar = unsafe { (*stream.as_mut_ptr()).codecpar };
506 unsafe {
508 (*codecpar).codec_type = AVMediaType::Subtitle.into();
509 }
510 let decoder_result = Decoder::with_options(&stream, DecoderOptions::default());
511
512 assert!(
513 decoder_result.is_err(),
514 "Expected Decoder creation to fail for non-video/audio codec type"
515 );
516 if let Err(err) = decoder_result {
517 match err {
518 crate::error::FfmpegError::NoDecoder => (),
519 _ => panic!("Unexpected error type: {:?}", err),
520 }
521 }
522 }
523
524 #[test]
525 fn test_video_decoder_deref_mut_safe() {
526 let valid_file_path = "../../assets/avc_aac_large.mp4";
527 let input = Input::open(valid_file_path).expect("Failed to open valid file");
528 let streams = input.streams();
529 let stream = streams
530 .iter()
531 .find(|s| {
532 s.codec_parameters()
533 .map(|p| AVMediaType(p.codec_type) == AVMediaType::Video)
534 .unwrap_or(false)
535 })
536 .expect("No video stream found");
537 let decoder_options = DecoderOptions {
538 codec: None,
539 thread_count: 2,
540 };
541 let decoder = Decoder::with_options(&stream, decoder_options).expect("Failed to create Decoder");
542 let mut video_decoder = match decoder {
543 Decoder::Video(video_decoder) => video_decoder,
544 _ => panic!("Expected a VideoDecoder, got something else"),
545 };
546 {
547 let generic_decoder = &mut *video_decoder;
548 let mut time_base = generic_decoder.time_base();
549 time_base.num = 1000;
550 time_base.den = 1;
551 generic_decoder.decoder.as_deref_mut_except().time_base = time_base;
552 }
553 let generic_decoder = &*video_decoder;
554 let time_base = generic_decoder.decoder.as_deref_except().time_base;
555
556 assert_eq!(time_base.num, 1000, "Expected time_base.num to be updated via DerefMut");
557 assert_eq!(time_base.den, 1, "Expected time_base.den to be updated via DerefMut");
558 }
559
560 #[test]
561 fn test_audio_decoder_deref_mut() {
562 let valid_file_path = "../../assets/avc_aac_large.mp4";
563 let input = Input::open(valid_file_path).expect("Failed to open valid file");
564 let streams = input.streams();
565 let stream = streams
566 .iter()
567 .find(|s| {
568 s.codec_parameters()
569 .map(|p| AVMediaType(p.codec_type) == AVMediaType::Audio)
570 .unwrap_or(false)
571 })
572 .expect("No audio stream found");
573 let decoder_options = DecoderOptions {
574 codec: None,
575 thread_count: 2,
576 };
577 let decoder = Decoder::with_options(&stream, decoder_options).expect("Failed to create Decoder");
578 let mut audio_decoder = match decoder {
579 Decoder::Audio(audio_decoder) => audio_decoder,
580 _ => panic!("Expected an AudioDecoder, got something else"),
581 };
582 {
583 let generic_decoder = &mut *audio_decoder;
584 let mut time_base = generic_decoder.time_base();
585 time_base.num = 48000;
586 time_base.den = 1;
587 generic_decoder.decoder.as_deref_mut_except().time_base = time_base;
588 }
589 let generic_decoder = &*audio_decoder;
590 let time_base = generic_decoder.decoder.as_deref_except().time_base;
591
592 assert_eq!(time_base.num, 48000, "Expected time_base.num to be updated via DerefMut");
593 assert_eq!(time_base.den, 1, "Expected time_base.den to be updated via DerefMut");
594 }
595
596 #[test]
597 fn test_decoder_video() {
598 let valid_file_path = "../../assets/avc_aac_large.mp4";
599 let mut input = Input::open(valid_file_path).expect("Failed to open valid file");
600 let streams = input.streams();
601 let video_stream = streams.best(AVMediaType::Video).expect("No video stream found");
602 let audio_stream = streams.best(AVMediaType::Audio).expect("No audio stream found");
603 let mut video_decoder = Decoder::new(&video_stream)
604 .expect("Failed to create decoder")
605 .video()
606 .expect("Failed to get video decoder");
607 let mut audio_decoder = Decoder::new(&audio_stream)
608 .expect("Failed to create decoder")
609 .audio()
610 .expect("Failed to get audio decoder");
611 let mut video_frames = Vec::new();
612 let mut audio_frames = Vec::new();
613
614 let video_stream_index = video_stream.index();
615 let audio_stream_index = audio_stream.index();
616
617 while let Some(packet) = input.receive_packet().expect("Failed to receive packet") {
618 if packet.stream_index() == video_stream_index {
619 video_decoder.send_packet(&packet).expect("Failed to send packet");
620 while let Some(frame) = video_decoder.receive_frame().expect("Failed to receive frame") {
621 video_frames.push(frame);
622 }
623 } else if packet.stream_index() == audio_stream_index {
624 audio_decoder.send_packet(&packet).expect("Failed to send packet");
625 while let Some(frame) = audio_decoder.receive_frame().expect("Failed to receive frame") {
626 audio_frames.push(frame);
627 }
628 }
629 }
630
631 video_decoder.send_eof().expect("Failed to send eof");
632 while let Some(frame) = video_decoder.receive_frame().expect("Failed to receive frame") {
633 video_frames.push(frame);
634 }
635
636 audio_decoder.send_eof().expect("Failed to send eof");
637 while let Some(frame) = audio_decoder.receive_frame().expect("Failed to receive frame") {
638 audio_frames.push(frame);
639 }
640
641 insta::assert_debug_snapshot!("test_decoder_video", video_frames);
642 insta::assert_debug_snapshot!("test_decoder_audio", audio_frames);
643 }
644}