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