media/
media_thread.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::sync::{Arc, Mutex};
6use std::thread;
7
8use compositing_traits::{WebrenderExternalImageRegistry, WebrenderImageHandlerType};
9use ipc_channel::ipc::{IpcSender, channel};
10use log::{trace, warn};
11use rustc_hash::FxHashMap;
12use webrender_api::ExternalImageId;
13
14/// GL player threading API entry point that lives in the
15/// constellation.
16use crate::{GLPlayerMsg, GLPlayerMsgForward};
17
18/// A GLPlayerThread manages the life cycle and message demultiplexing of
19/// a set of video players with GL render.
20pub struct GLPlayerThread {
21    /// Map of live players.
22    players: FxHashMap<u64, IpcSender<GLPlayerMsgForward>>,
23    /// List of registered webrender external images.
24    /// We use it to get an unique ID for new players.
25    external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
26}
27
28impl GLPlayerThread {
29    pub fn new(external_images: Arc<Mutex<WebrenderExternalImageRegistry>>) -> Self {
30        GLPlayerThread {
31            players: Default::default(),
32            external_images,
33        }
34    }
35
36    pub fn start(
37        external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
38    ) -> IpcSender<GLPlayerMsg> {
39        let (sender, receiver) = channel().unwrap();
40        thread::Builder::new()
41            .name("GLPlayer".to_owned())
42            .spawn(move || {
43                let mut renderer = GLPlayerThread::new(external_images);
44                loop {
45                    let msg = receiver.recv().unwrap();
46                    let exit = renderer.handle_msg(msg);
47                    if exit {
48                        return;
49                    }
50                }
51            })
52            .expect("Thread spawning failed");
53
54        sender
55    }
56
57    /// Handles a generic GLPlayerMsg message
58    #[inline]
59    fn handle_msg(&mut self, msg: GLPlayerMsg) -> bool {
60        trace!("processing {:?}", msg);
61        match msg {
62            GLPlayerMsg::RegisterPlayer(sender) => {
63                let id = self
64                    .external_images
65                    .lock()
66                    .unwrap()
67                    .next_id(WebrenderImageHandlerType::Media)
68                    .0;
69                self.players.insert(id, sender.clone());
70                sender.send(GLPlayerMsgForward::PlayerId(id)).unwrap();
71            },
72            GLPlayerMsg::UnregisterPlayer(id) => {
73                self.external_images
74                    .lock()
75                    .unwrap()
76                    .remove(&ExternalImageId(id));
77                if self.players.remove(&id).is_none() {
78                    warn!("Tried to remove an unknown player");
79                }
80            },
81            GLPlayerMsg::Lock(id, handler_sender) => {
82                if let Some(sender) = self.players.get(&id) {
83                    sender.send(GLPlayerMsgForward::Lock(handler_sender)).ok();
84                }
85            },
86            GLPlayerMsg::Unlock(id) => {
87                if let Some(sender) = self.players.get(&id) {
88                    sender.send(GLPlayerMsgForward::Unlock()).ok();
89                }
90            },
91            GLPlayerMsg::Exit => return true,
92        }
93
94        false
95    }
96}