servo_media_audio/
media_element_source_node.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::collections::HashMap;
6use std::collections::hash_map::Entry;
7use std::sync::mpsc::Sender;
8use std::sync::{Arc, Mutex};
9
10use malloc_size_of_derive::MallocSizeOf;
11use player::audio::AudioRenderer;
12
13use crate::block::{Block, Chunk, FRAMES_PER_BLOCK};
14use crate::node::{AudioNodeEngine, AudioNodeType, BlockInfo, ChannelInfo};
15
16#[derive(Debug, Clone, MallocSizeOf)]
17pub enum MediaElementSourceNodeMessage {
18    GetAudioRenderer(Sender<Arc<Mutex<dyn AudioRenderer>>>),
19}
20
21#[derive(AudioNodeCommon)]
22pub(crate) struct MediaElementSourceNode {
23    channel_info: ChannelInfo,
24    renderer: Arc<Mutex<dyn AudioRenderer>>,
25    buffers: Arc<Mutex<Vec<Vec<f32>>>>,
26    playback_offset: usize,
27}
28
29impl MediaElementSourceNode {
30    pub fn new(channel_info: ChannelInfo) -> Self {
31        let buffers = Arc::new(Mutex::new(Vec::new()));
32        let renderer = Arc::new(Mutex::new(MediaElementSourceNodeRenderer::new(
33            buffers.clone(),
34        )));
35        Self {
36            channel_info,
37            renderer,
38            buffers,
39            playback_offset: 0,
40        }
41    }
42
43    pub fn handle_message(&mut self, message: MediaElementSourceNodeMessage, _: f32) {
44        match message {
45            MediaElementSourceNodeMessage::GetAudioRenderer(sender) => {
46                let _ = sender.send(self.renderer.clone());
47            },
48        }
49    }
50}
51
52impl AudioNodeEngine for MediaElementSourceNode {
53    fn node_type(&self) -> AudioNodeType {
54        AudioNodeType::MediaElementSourceNode
55    }
56
57    fn process(&mut self, mut inputs: Chunk, _info: &BlockInfo) -> Chunk {
58        debug_assert!(inputs.is_empty());
59
60        let buffers = self.buffers.lock().unwrap();
61        let chans = buffers.len() as u8;
62
63        if chans == 0 {
64            inputs.blocks.push(Default::default());
65            return inputs;
66        }
67
68        let len = buffers[0].len();
69
70        let frames_per_block = FRAMES_PER_BLOCK.0 as usize;
71        let samples_to_copy = if self.playback_offset + frames_per_block > len {
72            len - self.playback_offset
73        } else {
74            frames_per_block
75        };
76        let next_offset = self.playback_offset + samples_to_copy;
77        if samples_to_copy == FRAMES_PER_BLOCK.0 as usize {
78            // copy entire chan
79            let mut block = Block::empty();
80            for chan in 0..chans {
81                block.push_chan(&buffers[chan as usize][self.playback_offset..next_offset]);
82            }
83            inputs.blocks.push(block)
84        } else {
85            // silent fill and copy
86            let mut block = Block::default();
87            block.repeat(chans);
88            block.explicit_repeat();
89            for chan in 0..chans {
90                let data = block.data_chan_mut(chan);
91                let (_, data) = data.split_at_mut(0);
92                let (data, _) = data.split_at_mut(samples_to_copy);
93                data.copy_from_slice(&buffers[chan as usize][self.playback_offset..next_offset]);
94            }
95            inputs.blocks.push(block)
96        }
97
98        self.playback_offset = next_offset;
99
100        inputs
101    }
102
103    fn input_count(&self) -> u32 {
104        0
105    }
106
107    make_message_handler!(MediaElementSourceNode: handle_message);
108}
109
110struct MediaElementSourceNodeRenderer {
111    buffers: Arc<Mutex<Vec<Vec<f32>>>>,
112    channels: HashMap<u32, usize>,
113}
114
115impl MediaElementSourceNodeRenderer {
116    pub fn new(buffers: Arc<Mutex<Vec<Vec<f32>>>>) -> Self {
117        Self {
118            buffers,
119            channels: HashMap::new(),
120        }
121    }
122}
123
124impl AudioRenderer for MediaElementSourceNodeRenderer {
125    fn render(&mut self, sample: Box<dyn AsRef<[f32]>>, channel_pos: u32) {
126        let channel = match self.channels.entry(channel_pos) {
127            Entry::Occupied(entry) => *entry.get(),
128            Entry::Vacant(entry) => {
129                let mut buffers = self.buffers.lock().unwrap();
130                let len = buffers.len();
131                buffers.resize(len + 1, Vec::new());
132                *entry.insert(buffers.len())
133            },
134        };
135        self.buffers.lock().unwrap()[channel - 1].extend_from_slice((*sample).as_ref());
136    }
137}