• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nomalab / stainless-ffmpeg / #101

17 Oct 2025 09:43AM UTC coverage: 64.609% (+0.04%) from 64.571%
#101

push

1685 of 2608 relevant lines covered (64.61%)

0.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.33
/src/audio_decoder.rs
1
use crate::{format_context::FormatContext, frame::Frame, packet::Packet, tools};
2
use ffmpeg_sys_next::*;
3
use std::ptr::null_mut;
4

5
#[derive(Debug)]
6
pub struct AudioDecoder {
7
  pub identifier: String,
8
  pub stream_index: isize,
9
  pub codec_context: *mut AVCodecContext,
10
}
11

12
impl AudioDecoder {
13
  pub fn new(
1✔
14
    identifier: String,
15
    format: &FormatContext,
16
    stream_index: isize,
17
  ) -> Result<Self, String> {
18
    unsafe {
19
      let codec = avcodec_find_decoder(format.get_codec_id(stream_index));
2✔
20
      let mut codec_context = avcodec_alloc_context3(codec);
1✔
21

22
      check_result!(
1✔
23
        avcodec_parameters_to_context(
24
          codec_context,
25
          (**(*format.format_context).streams.offset(stream_index)).codecpar
26
        ),
27
        {
28
          avcodec_free_context(&mut codec_context);
29
        }
30
      );
31
      check_result!(avcodec_open2(codec_context, codec, null_mut()), {
×
32
        avcodec_free_context(&mut codec_context);
33
      });
34

35
      Ok(AudioDecoder {
1✔
36
        identifier,
1✔
37
        stream_index,
38
        codec_context,
1✔
39
      })
40
    }
41
  }
42

43
  pub fn get_sample_rate(&self) -> i32 {
1✔
44
    unsafe { (*self.codec_context).sample_rate }
1✔
45
  }
46

47
  pub fn get_nb_channels(&self) -> i32 {
1✔
48
    unsafe { (*self.codec_context).channels }
1✔
49
  }
50

51
  pub fn get_channel_layout(&self) -> u64 {
1✔
52
    unsafe { (*self.codec_context).channel_layout }
1✔
53
  }
54

55
  pub fn get_sample_fmt_name(&self) -> String {
1✔
56
    unsafe {
57
      let input_fmt_str = av_get_sample_fmt_name((*self.codec_context).sample_fmt);
1✔
58
      tools::to_string(input_fmt_str)
1✔
59
    }
60
  }
61

62
  pub fn decode(&self, packet: &Packet) -> Result<Frame, String> {
1✔
63
    if packet.get_stream_index() != self.stream_index {
1✔
64
      return Err("bad stream".to_string());
×
65
    }
66
    unsafe {
67
      check_result!(avcodec_send_packet(self.codec_context, packet.packet));
1✔
68

69
      let frame = av_frame_alloc();
1✔
70
      check_result!(avcodec_receive_frame(self.codec_context, frame));
1✔
71

72
      Ok(Frame {
1✔
73
        frame,
74
        name: Some(self.identifier.clone()),
1✔
75
        index: self.stream_index as usize,
1✔
76
      })
77
    }
78
  }
79
}
80

81
impl Drop for AudioDecoder {
82
  fn drop(&mut self) {
1✔
83
    unsafe {
84
      if !self.codec_context.is_null() {
1✔
85
        avcodec_close(self.codec_context);
1✔
86
        avcodec_free_context(&mut self.codec_context);
1✔
87
      }
88
    }
89
  }
90
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc