[WebRTC] Add display feature for video APIs (#5442)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Remoting / WebRTC / MediaStreamTrack.cs
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Diagnostics;
19 using static Interop;
20
21 namespace Tizen.Multimedia.Remoting
22 {
23     /// <summary>
24     /// Provides the ability to control audio/video track.
25     /// </summary>
26     /// <since_tizen> 9 </since_tizen>
27     public sealed class MediaStreamTrack : IDisplayable<WebRTCErrorCode>
28     {
29         private WebRTC _webRtc;
30         private uint _trackId;
31         private Display _display;
32
33         internal MediaStreamTrack(WebRTC webRtc, MediaType type, uint trackId)
34         {
35             _webRtc = webRtc;
36             _trackId = trackId;
37             Type = type;
38         }
39
40         /// <summary>
41         /// Gets the the of media stream track.
42         /// </summary>
43         /// <value><see cref="MediaType"/></value>
44         /// <since_tizen> 9 </since_tizen>
45         public MediaType Type { get; }
46
47         private WebRTCErrorCode SetDisplay(Display display)
48             => display.ApplyTo(this);
49
50         private void ReplaceDisplay(Display newDisplay)
51         {
52             _display?.SetOwner(null);
53             _display = newDisplay;
54             _display?.SetOwner(this);
55         }
56
57         /// <summary>
58         /// Gets or sets the display to show remote video.
59         /// </summary>
60         /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
61         /// <remarks>
62         /// If user set video source with <see cref="TransceiverDirection.SendRecv"/>, <see cref="Display"/> must be set.<br/>
63         /// If not, the received video will fill entire screen.<br/>
64         /// If remote track, <see cref="Display"/> must be set in <see cref="WebRTC.TrackAdded"/> event.<br/>
65         /// The display is created with <see cref="MediaView"/>.
66         /// </remarks>
67         /// <feature>http://tizen.org/feature/display</feature>
68         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
69         /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed of.</exception>
70         /// <exception cref="ArgumentException">The value has already been assigned to another WebRTC.</exception>
71         /// <exception cref="InvalidOperationException">
72         /// The WebRTC is not called in <see cref="WebRTC.TrackAdded"/> event.
73         /// -or-<br/>
74         /// This MediaStreamTrack is not Video.
75         /// </exception>
76         /// <since_tizen> 9 </since_tizen>
77         public Display Display
78         {
79             get
80             {
81                 if (!Features.IsSupported(WebRTCFeatures.Display))
82                 {
83                     throw new NotSupportedException("Display feature is not supported.");
84                 }
85
86                 return _display;
87             }
88             set
89             {
90                 if (!Features.IsSupported(WebRTCFeatures.Display))
91                 {
92                     throw new NotSupportedException("Display feature is not supported.");
93                 }
94
95                 if (Type != MediaType.Video)
96                 {
97                     throw new InvalidOperationException("This property is only for video track.");
98                 }
99
100                 if (value == null)
101                 {
102                     throw new ArgumentNullException(nameof(value), "Display cannot be null.");
103                 }
104
105                 if (value?.Owner != null)
106                 {
107                     if (ReferenceEquals(this, value.Owner))
108                     {
109                         throw new ArgumentException("The display has already been assigned to another.");
110                     }
111                 }
112                 else
113                 {
114                     SetDisplay(value).ThrowIfFailed("Failed to configure display of the MediaStreamTrack");
115                     ReplaceDisplay(value);
116                 }
117             }
118         }
119
120         WebRTCErrorCode IDisplayable<WebRTCErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
121         {
122             Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
123             Debug.Assert(type != DisplayType.None);
124
125             return NativeWebRTC.SetDisplay(_webRtc.Handle, _trackId,
126                 type == DisplayType.Overlay ? WebRTCDisplayType.Overlay : WebRTCDisplayType.Evas, evasObject);
127         }
128
129         WebRTCErrorCode IDisplayable<WebRTCErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
130         {
131             return NativeWebRTC.SetEcoreDisplay(_webRtc.Handle, _trackId, windowHandle);
132         }
133
134         /// <summary>
135         /// Gets or sets the display mode.
136         /// </summary>
137         /// <remarks>
138         /// This property is meaningful only in overlay or EVAS surface display type.
139         /// </remarks>
140         /// <feature>http://tizen.org/feature/display</feature>
141         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
142         /// <value>A <see cref="WebRTCDisplayMode"/> that specifies the display mode.</value>
143         /// <exception cref="ArgumentException">Display mode type is incorrect.</exception>
144         /// <exception cref="InvalidOperationException"><see cref="Display"/> is not set.</exception>
145         /// <since_tizen> 9 </since_tizen>
146         public WebRTCDisplayMode DisplayMode
147         {
148             get
149             {
150                 if (!Features.IsSupported(WebRTCFeatures.Display))
151                 {
152                     throw new NotSupportedException("Display feature is not supported.");
153                 }
154
155                 if (Type != MediaType.Video)
156                 {
157                     throw new InvalidOperationException("This property is only for video track.");
158                 }
159
160                 NativeWebRTC.GetDisplayMode(_webRtc.Handle, _trackId, out var val).
161                     ThrowIfFailed("Failed to get WebRTC display mode");
162
163                 return val;
164             }
165             set
166             {
167                 if (!Features.IsSupported(WebRTCFeatures.Display))
168                 {
169                     throw new NotSupportedException("Display feature is not supported.");
170                 }
171
172                 if (Type != MediaType.Video)
173                 {
174                     throw new InvalidOperationException("This property is only for video track.");
175                 }
176
177                 ValidationUtil.ValidateEnum(typeof(WebRTCDisplayMode), value, nameof(value));
178
179                 NativeWebRTC.SetDisplayMode(_webRtc.Handle, _trackId, value).
180                     ThrowIfFailed("Failed to set WebRTC display mode.");
181             }
182         }
183
184         /// <summary>
185         /// Gets or sets the display visibility.
186         /// </summary>
187         /// <value>true if WebRTC display is visible, otherwise false.</value>
188         /// <remarks>
189         /// This property is meaningful only in overlay or EVAS surface display type.
190         /// </remarks>
191         /// <feature>http://tizen.org/feature/display</feature>
192         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
193         /// <exception cref="InvalidOperationException"><see cref="Display"/> is not set.</exception>
194         /// <since_tizen> 9 </since_tizen>
195         public bool DisplayVisible
196         {
197             get
198             {
199                 if (!Features.IsSupported(WebRTCFeatures.Display))
200                 {
201                     throw new NotSupportedException("Display feature is not supported.");
202                 }
203
204                 if (Type != MediaType.Video)
205                 {
206                     throw new InvalidOperationException("This property is only for video track.");
207                 }
208
209                 NativeWebRTC.GetDisplayVisible(_webRtc.Handle, _trackId, out bool val).
210                     ThrowIfFailed("Failed to get visible status");
211
212                 return val;
213             }
214             set
215             {
216                 if (!Features.IsSupported(WebRTCFeatures.Display))
217                 {
218                     throw new NotSupportedException("Display feature is not supported.");
219                 }
220
221                 if (Type != MediaType.Video)
222                 {
223                     throw new InvalidOperationException("This property is only for video track.");
224                 }
225
226                 NativeWebRTC.SetDisplayVisible(_webRtc.Handle, _trackId, value).
227                     ThrowIfFailed("Failed to set display status.");
228             }
229         }
230
231         /// <summary>
232         /// Gets or sets the mute status of the audio track.
233         /// </summary>
234         /// <value>true if audio is muted, otherwise false. The default value is false.</value>
235         /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed.</exception>
236         /// <exception cref="InvalidOperationException">This MediaStreamTrack is not Audio.</exception>
237         /// <since_tizen> 11 </since_tizen>
238         public bool Mute
239         {
240             get
241             {
242                 if (Type != MediaType.Audio)
243                 {
244                     throw new InvalidOperationException("This property is only for audio track.");
245                 }
246
247                 NativeWebRTC.GetAudioMute(_webRtc.Handle, _trackId, out bool val).
248                     ThrowIfFailed("Failed to get audio mute status");
249
250                 return val;
251             }
252             set
253             {
254                 if (Type != MediaType.Audio)
255                 {
256                     throw new InvalidOperationException("This property is only for audio track.");
257                 }
258
259                 NativeWebRTC.SetAudioMute(_webRtc.Handle, _trackId, value).
260                     ThrowIfFailed("Failed to set audio mute status.");
261             }
262         }
263
264         /// <summary>
265         /// Applies the audio stream policy to remote track.
266         /// </summary>
267         /// <param name="policy">The <see cref="AudioStreamPolicy"/> to apply.</param>
268         /// <remarks>
269         /// This must be called in <see cref="WebRTC.TrackAdded"/> event.<br/>
270         /// <br/>
271         /// <see cref="WebRTC"/> does not support all <see cref="AudioStreamType"/>.<br/>
272         /// Supported types are <see cref="AudioStreamType.Media"/>, <see cref="AudioStreamType.Voip"/>,
273         /// <see cref="AudioStreamType.MediaExternalOnly"/>.
274         /// </remarks>
275         /// <exception cref="ArgumentNullException"><paramref name="policy"/> is null.</exception>
276         /// <exception cref="InvalidOperationException">
277         /// <see cref="WebRTC.AudioFrameEncoded"/> was set.<br/>
278         /// -or-<br/>
279         /// This method was not called in <see cref="WebRTC.TrackAdded"/> event.
280         /// -or-<br/>
281         /// This MediaStreamTrack is not Audio.
282         /// </exception>
283         /// <exception cref="NotSupportedException">
284         ///     <see cref="AudioStreamType"/> of <paramref name="policy"/> is not supported on the current platform.
285         /// </exception>
286         /// <exception cref="ObjectDisposedException">
287         ///     The WebRTC has already been disposed.<br/>
288         ///     -or-<br/>
289         ///     <paramref name="policy"/> has already been disposed.
290         /// </exception>
291         /// <seealso cref="AudioStreamPolicy"/>
292         /// <seealso cref="WebRTC.TrackAdded"/>
293         /// <since_tizen> 9 </since_tizen>
294         public void ApplyAudioStreamPolicy(AudioStreamPolicy policy)
295         {
296             if (policy == null)
297             {
298                 throw new ArgumentNullException(nameof(policy));
299             }
300
301             if (Type != MediaType.Audio)
302             {
303                 throw new InvalidOperationException("This method is only for audio track.");
304             }
305
306             var ret = NativeWebRTC.SetAudioStreamPolicy(_webRtc.Handle, _trackId, policy.Handle);
307
308             if (ret == WebRTCErrorCode.InvalidArgument)
309             {
310                 throw new NotSupportedException("The specified policy is not supported on the current system.");
311             }
312
313             ret.ThrowIfFailed("Failed to set the audio stream policy to the WebRTC");
314         }
315     }
316 }