1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (c) 2014 Richard Diamond & contributors.
//
// This file is part of the Rust PPApi project.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use ffi;
use ppb::{MediaStreamVideoTrackIf, get_media_stream_video_track};
use super::{Callback, CallbackArgs, StringVar, Code, Result, Resource};
use super::video_frame::{self, VideoFrame};
/// Created on the JS side and sent in a message.
#[derive(Hash, Eq, PartialEq, Debug)]
pub struct VideoTrack(ffi::PP_Resource);
impl_clone_drop_for!(VideoTrack);
impl_resource_for!(VideoTrack, ResourceType::VideoFrameRes);
#[doc(hidden)]
impl From<ffi::PP_Resource> for VideoTrack {
fn from(v: ffi::PP_Resource) -> VideoTrack {
debug_assert!(get_media_stream_video_track().is(v));
VideoTrack(v)
}
}
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
pub enum Attr {
/// The number of buffer frames. Chrome may use more or less. How many
/// frames to buffer depends on usage - request at least 2 to make sure
/// latency doesn't cause lost frames. If the plugin expects to hold on to
/// more than one frame at a time (e.g. to do multi-frame processing), it
/// should request that many more. If this attribute is not specified or
/// value 0 is specified for this attribute, the default value will be
/// used.
Buffers(u32),
/// The width of video frames in pixels.
///
/// It should be a multiple of 4. If the specified size is different from
/// the video source (webcam), frames will be scaled to specified size. If
/// this attribute is not specified or value 0 is specified, the original
/// frame size of the video track will be used.
///
/// Maximum value: 4096 (4K resolution).
Width(u32),
/// The height of video frames in pixels.
///
/// It should be a multiple of 4. If the specified size is different from
/// the video source (webcam), frames will be scaled to specified size. If
/// this attribute is not specified or value 0 is specified, the original
/// frame size of the video track will be used.
///
/// Maximum value: 4096 (4K resolution).
Height(u32),
/// The format of video frames.
///
/// The attribute value is a `video_frame::Format`. If the specified
/// format is different from the video source (webcam), frames will be
/// converted to specified format. If this attribute is not specified or
/// value `Format::Unknown` is specified, the orignal frame format of the
/// video track will be used.
Format(video_frame::Format),
}
impl Attr {
#[doc(hidden)]
pub fn to_ffi(self) -> ffi::PP_MediaStreamVideoTrack_Attrib {
match self {
Attr::Buffers(..) => ffi::PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES,
Attr::Width(..) => ffi::PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH,
Attr::Height(..) => ffi::PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT,
Attr::Format(..) => ffi::PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT,
}
}
}
impl VideoTrack {
pub fn configure<'a, T: AsRef<&'a [Attr]>, F>(&self, attrs: T, callback: F) -> Code
where F: Callback
{
use std::cmp::min;
let mut nattrs: Vec<ffi::PP_MediaStreamVideoTrack_Attrib> =
Vec::with_capacity(attrs.as_ref().len() + 1);
for attr in attrs.as_ref().iter() {
nattrs.push(attr.to_ffi());
match attr {
&Attr::Buffers(c) => {
nattrs.push(c as ffi::PP_MediaStreamVideoTrack_Attrib);
},
&Attr::Width(c) | &Attr::Height(c) => {
nattrs.push(min(c, 4096) as ffi::PP_MediaStreamVideoTrack_Attrib);
},
&Attr::Format(f) => {
nattrs.push(f.to_ffi());
},
}
}
nattrs.push(ffi::PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE);
get_media_stream_video_track()
.configure(self.unwrap(), nattrs.as_ref(), callback.to_ffi_callback())
}
pub fn get_attr(&self, attr: Attr) -> Result<Attr> {
get_media_stream_video_track()
.get_attrib(self.unwrap(), attr.to_ffi())
.map(|i| {
match attr {
Attr::Buffers(..) => Attr::Buffers(i as u32),
Attr::Width(..) => Attr::Width(i as u32),
Attr::Height(..) => Attr::Height(i as u32),
Attr::Format(..) => Attr::Format(From::from(i as u32))
}
})
}
pub fn get_id(&self) -> StringVar {
From::from(get_media_stream_video_track().get_id(self.unwrap()))
}
pub fn has_ended(&self) -> bool {
get_media_stream_video_track()
.has_ended(self.unwrap())
}
pub fn get_frame<F>(&self, f: F) -> Code
where F: CallbackArgs<VideoFrame>
{
fn mapper(res: ffi::PP_Resource) -> VideoFrame { From::from(res) }
let (cb, frame) = f.to_ffi_callback(0, mapper);
get_media_stream_video_track()
.get_frame(self.unwrap(), frame, cb)
}
pub fn recycle_frame(&self, frame: VideoFrame) -> Code {
get_media_stream_video_track()
.recycle_frame(self.unwrap(), frame.unwrap())
}
pub fn close(self) {
get_media_stream_video_track()
.close(self.unwrap())
}
}