[MediaPlayer] Add new API to set video codec type (#5359)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.MediaPlayer / Player / Player.Properties.cs
1 /*
2  * Copyright (c) 2018 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 using System;
17 using System.Diagnostics;
18 using NativeDisplay = Interop.Display;
19 using static Interop;
20
21 namespace Tizen.Multimedia
22 {
23     /// <summary>
24     /// Represents properties for streaming buffering time.
25     /// </summary>
26     /// <since_tizen> 5 </since_tizen>
27     public struct PlayerBufferingTime
28     {
29         /// <summary>
30         /// Initializes a new instance of the PlayerBufferingTime struct.
31         /// </summary>
32         /// <param name="preBufferMillisecond">A duration of buffering data that must be prerolled to start playback.</param>
33         /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation.
34         /// 0 : use platform default value which could be different depending on the streaming type and network status. (the initial value)
35         /// -1 : use current value. (since 5.5)
36         /// <param name="reBufferMillisecond">A duration of buffering data that must be prerolled to resume playback,
37         /// when player is internally paused for buffering.
38         /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation.
39         /// 0 : use platform default value, which depends on the streaming type and network status. It is set as the initial value of this parameter.
40         /// If the player state is <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/>,
41         /// this function will return correct time value instead of 0. (since 5.5)
42         /// -1 : use current value. (since 5.5)</param>
43         /// <since_tizen> 5 </since_tizen>
44         public PlayerBufferingTime(int preBufferMillisecond = -1, int reBufferMillisecond = -1)
45         {
46             PreBufferMillisecond = preBufferMillisecond;
47             ReBufferMillisecond = reBufferMillisecond;
48         }
49
50         /// <summary>
51         /// Gets or sets the duration of buffering data that must be prerolled to start playback.
52         /// </summary>
53         /// <since_tizen> 5 </since_tizen>
54         public int PreBufferMillisecond
55         {
56             get;
57             set;
58         }
59
60         /// <summary>
61         /// Gets or sets the duration of buffering data that must be prerolled to resume playback
62         /// if player enters pause state for buffering.
63         /// </summary>
64         /// <since_tizen> 5 </since_tizen>
65         public int ReBufferMillisecond
66         {
67             get;
68             set;
69         }
70     }
71     /// <since_tizen> 3 </since_tizen>
72     public partial class Player
73     {
74         /// <summary>
75         /// Gets the native handle of the player.
76         /// </summary>
77         /// <value>An IntPtr that contains the native handle of the player.</value>
78         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
79         /// <since_tizen> 3 </since_tizen>
80         public IntPtr Handle
81         {
82             get
83             {
84                 ValidateNotDisposed();
85                 return _handle.DangerousGetHandle();
86             }
87         }
88
89         #region Network configuration
90         private string _cookie = "";
91         private string _userAgent = "";
92         private const int MinBufferingTime = -1;
93
94         /// <summary>
95         /// Gets or sets the cookie for streaming playback.
96         /// </summary>
97         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
98         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
99         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
100         /// <exception cref="ArgumentNullException">The value to set is null.</exception>
101         /// <since_tizen> 3 </since_tizen>
102         public string Cookie
103         {
104             get
105             {
106                 return _cookie;
107             }
108             set
109             {
110                 ValidatePlayerState(PlayerState.Idle);
111
112                 if (value == null)
113                 {
114                     throw new ArgumentNullException(nameof(value), "Cookie can't be null.");
115                 }
116
117                 NativePlayer.SetStreamingCookie(Handle, value, value.Length).
118                     ThrowIfFailed(this, "Failed to set the cookie to the player");
119
120                 _cookie = value;
121             }
122         }
123
124         /// <summary>
125         /// Gets or sets the user agent for streaming playback.
126         /// </summary>
127         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
128         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
129         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
130         /// <exception cref="ArgumentNullException">The value to set is null.</exception>
131         /// <since_tizen> 3 </since_tizen>
132         public string UserAgent
133         {
134             get
135             {
136                 return _userAgent;
137             }
138             set
139             {
140                 ValidatePlayerState(PlayerState.Idle);
141
142                 if (value == null)
143                 {
144                     throw new ArgumentNullException(nameof(value), "UserAgent can't be null.");
145                 }
146
147                 NativePlayer.SetStreamingUserAgent(Handle, value, value.Length).
148                     ThrowIfFailed(this, "Failed to set the user agent to the player");
149
150                 _userAgent = value;
151             }
152         }
153
154         /// <summary>
155         /// Gets or sets the streaming buffering time.
156         /// </summary>
157         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
158         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
159         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
160         /// <exception cref="ArgumentOutOfRangeException">
161         ///     <pramref name="PreBufferMillisecond"/> is less than -1.<br/>
162         ///     -or-<br/>
163         ///     <pramref name="ReBufferMillisecond"/> is less than -1.<br/>
164         /// </exception>
165         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
166         /// <seealso cref="PlayerBufferingTime"/>
167         /// <since_tizen> 5 </since_tizen>
168         public PlayerBufferingTime BufferingTime
169         {
170             get
171             {
172                 ValidateNotDisposed();
173
174                 NativePlayer.GetStreamingBufferingTime(Handle, out var PreBuffMillisecond, out var ReBuffMillisecond).
175                         ThrowIfFailed(this, "Failed to get the buffering time of the player");
176
177                 return new PlayerBufferingTime(PreBuffMillisecond, ReBuffMillisecond);
178             }
179             set
180             {
181                 ValidatePlayerState(PlayerState.Idle);
182
183                 if (value.PreBufferMillisecond < MinBufferingTime || value.ReBufferMillisecond < MinBufferingTime)
184                 {
185                     throw new ArgumentOutOfRangeException(nameof(value), value,
186                         $"invalid range, got { value.PreBufferMillisecond }, { value.ReBufferMillisecond }.");
187                 }
188
189                 NativePlayer.SetStreamingBufferingTime(Handle, value.PreBufferMillisecond, value.ReBufferMillisecond).
190                     ThrowIfFailed(this, "Failed to set the buffering time of the player");
191             }
192         }
193         #endregion
194
195         /// <summary>
196         /// Gets the state of the player.
197         /// </summary>
198         /// <value>The current state of the player.</value>
199         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
200         /// <since_tizen> 3 </since_tizen>
201         public PlayerState State
202         {
203             get
204             {
205                 ValidateNotDisposed();
206
207                 if (IsPreparing())
208                 {
209                     return PlayerState.Preparing;
210                 }
211
212                 NativePlayer.GetState(Handle, out var state).
213                     ThrowIfFailed(this, "Failed to retrieve the state of the player");
214
215                 Debug.Assert(Enum.IsDefined(typeof(PlayerState), state));
216
217                 return (PlayerState)state;
218             }
219         }
220
221         /// <summary>
222         /// Gets or sets the audio latency mode.
223         /// </summary>
224         /// <value>A <see cref="AudioLatencyMode"/> that specifies the mode. The default is <see cref="AudioLatencyMode.Mid"/>.</value>
225         /// <remarks>
226         /// If the mode is <see cref="AudioLatencyMode.High"/>,
227         /// audio output interval can be increased, so it can keep more audio data to play.
228         /// But, state transition like pause or resume can be more slower than default(<see cref="AudioLatencyMode.Mid"/>).
229         /// </remarks>
230         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
231         /// <exception cref="ArgumentException">The value is not valid.</exception>
232         /// <exception cref="NotAvailableException">
233         ///     If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
234         /// </exception>
235         /// <seealso cref="AudioOffload"/>
236         /// <since_tizen> 3 </since_tizen>
237         public AudioLatencyMode AudioLatencyMode
238         {
239             get
240             {
241                 AudioOffload.CheckDisabled();
242
243                 NativePlayer.GetAudioLatencyMode(Handle, out var value).
244                     ThrowIfFailed(this, "Failed to get the audio latency mode of the player");
245
246                 return value;
247             }
248             set
249             {
250                 ValidateNotDisposed();
251                 AudioOffload.CheckDisabled();
252
253                 ValidationUtil.ValidateEnum(typeof(AudioLatencyMode), value, nameof(value));
254
255                 NativePlayer.SetAudioLatencyMode(Handle, value).
256                     ThrowIfFailed(this, "Failed to set the audio latency mode of the player");
257             }
258         }
259
260         /// <summary>
261         /// Gets or sets the looping state.
262         /// </summary>
263         /// <value>true if the playback is looping; otherwise, false. The default value is false.</value>
264         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
265         /// <since_tizen> 3 </since_tizen>
266         public bool IsLooping
267         {
268             get
269             {
270                 NativePlayer.IsLooping(Handle, out var value).
271                     ThrowIfFailed(this, "Failed to get the looping state of the player");
272
273                 return value;
274             }
275             set
276             {
277                 ValidateNotDisposed();
278
279                 NativePlayer.SetLooping(Handle, value).
280                     ThrowIfFailed(this, "Failed to set the looping state of the player");
281             }
282         }
283
284         #region Display methods
285
286         private PlayerDisplaySettings _displaySettings;
287
288         /// <summary>
289         /// Gets the display settings.
290         /// </summary>
291         /// <value>A <see cref="PlayerDisplaySettings"/> that specifies the display settings.</value>
292         /// <since_tizen> 3 </since_tizen>
293         public PlayerDisplaySettings DisplaySettings => _displaySettings;
294
295         private Display _display;
296
297         private bool _uiSync;
298
299         private PlayerErrorCode SetDisplay(Display display)
300         {
301             if (display == null)
302             {
303                 return NativeDisplay.SetDisplay(Handle, PlayerDisplayType.None, IntPtr.Zero);
304             }
305
306             return display.ApplyTo(this);
307         }
308
309         private void ReplaceDisplay(Display newDisplay)
310         {
311             _display?.SetOwner(null);
312             _display = newDisplay;
313             _display?.SetOwner(this);
314         }
315
316         /// <summary>
317         /// Gets or sets the display.
318         /// </summary>
319         /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
320         /// <remarks>
321         ///     The player must be in the <see cref="PlayerState.Idle"/> state.<br/>
322         ///     The raw video feature(http://tizen.org/feature/multimedia.raw_video) is required if
323         ///     the display is created with <see cref="MediaView"/>.<br/>
324         ///     If a user wants to use video and UI sync mode, please use <see cref="Tizen.Multimedia.Display(NUI.Window, bool)"/>.(Since tizen 6.5)<br/>
325         ///     But <see cref="Tizen.Multimedia.Player.DisplaySettings"/> is not supported in UI sync mode.
326         /// </remarks>
327         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
328         /// <exception cref="ArgumentException">The value has already been assigned to another player.</exception>
329         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
330         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
331         /// <since_tizen> 3 </since_tizen>
332         public Display Display
333         {
334             get
335             {
336                 return _display;
337             }
338             set
339             {
340                 ValidatePlayerState(PlayerState.Idle);
341
342                 if (value != null && value.HasMediaView)
343                 {
344                     ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
345                 }
346
347                 if (value?.Owner != null)
348                 {
349                     if (ReferenceEquals(this, value.Owner))
350                     {
351                         return;
352                     }
353
354                     throw new ArgumentException("The display has already been assigned to another.");
355                 }
356
357                 _uiSync = value?.UiSync ?? false;
358
359                 SetDisplay(value).ThrowIfFailed(this, "Failed to configure display of the player");
360
361                 ReplaceDisplay(value);
362             }
363         }
364
365         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
366         {
367             Debug.Assert(IsDisposed == false);
368
369             Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
370             Debug.Assert(type != DisplayType.None);
371
372             return NativeDisplay.SetDisplay(Handle,
373                 type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject);
374         }
375
376         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
377         {
378             Debug.Assert(IsDisposed == false);
379
380             return NativeDisplay.SetEcoreDisplay(Handle,
381                 _uiSync ? PlayerDisplayType.OverlayUISync : PlayerDisplayType.Overlay, windowHandle);
382         }
383         #endregion
384
385         private PlayerTrackInfo _audioTrack;
386
387         /// <summary>
388         /// Gets the track info for the audio.
389         /// </summary>
390         /// <value>A <see cref="PlayerTrackInfo"/> for audio.</value>
391         /// <since_tizen> 3 </since_tizen>
392         public PlayerTrackInfo AudioTrackInfo
393         {
394             get
395             {
396                 if (_audioTrack == null)
397                 {
398                     _audioTrack = new PlayerTrackInfo(this, StreamType.Audio);
399                 }
400                 return _audioTrack;
401             }
402         }
403
404         private PlayerTrackInfo _subtitleTrackInfo;
405
406         /// <summary>
407         /// Gets the track info for the subtitle.
408         /// </summary>
409         /// <value>A <see cref="PlayerTrackInfo"/> for the subtitle.</value>
410         /// <since_tizen> 3 </since_tizen>
411         public PlayerTrackInfo SubtitleTrackInfo
412         {
413             get
414             {
415                 if (_subtitleTrackInfo == null)
416                 {
417                     _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text);
418                 }
419                 return _subtitleTrackInfo;
420             }
421         }
422
423         private StreamInfo _streamInfo;
424
425         /// <summary>
426         /// Gets the stream information.
427         /// </summary>
428         /// <value>A <see cref="StreamInfo"/> for this player.</value>
429         /// <since_tizen> 3 </since_tizen>
430         public StreamInfo StreamInfo
431         {
432             get
433             {
434                 if (_streamInfo == null)
435                 {
436                     _streamInfo = new StreamInfo(this);
437                 }
438                 return _streamInfo;
439             }
440         }
441
442         private AudioEffect _audioEffect;
443
444         /// <summary>
445         /// Gets the audio effect.
446         /// </summary>
447         /// <feature>http://tizen.org/feature/multimedia.custom_audio_effect</feature>
448         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
449         /// <since_tizen> 3 </since_tizen>
450         public AudioEffect AudioEffect
451         {
452             get
453             {
454                 if (_audioEffect == null)
455                 {
456                     throw new NotSupportedException($"The feature({PlayerFeatures.AudioEffect}) is not supported.");
457                 }
458
459                 return _audioEffect;
460             }
461         }
462
463         /// <summary>
464         /// Gets or sets the mute state.
465         /// </summary>
466         /// <value>true if the player is muted; otherwise, false.</value>
467         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
468         /// <since_tizen> 3 </since_tizen>
469         public bool Muted
470         {
471             get
472             {
473                 NativePlayer.IsMuted(Handle, out var value).
474                     ThrowIfFailed(this, "Failed to get the mute state of the player");
475
476                 Log.Info(PlayerLog.Tag, "get mute : " + value);
477
478                 return value;
479             }
480             set
481             {
482                 NativePlayer.SetMute(Handle, value).ThrowIfFailed(this, "Failed to set the mute state of the player");
483             }
484         }
485
486         /// <summary>
487         /// Gets or sets the current volume.
488         /// </summary>
489         /// <remarks>Valid volume range is from 0 to 1.0, inclusive.</remarks>
490         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
491         /// <exception cref="ArgumentOutOfRangeException">
492         ///     <paramref name="value"/> is less than zero.<br/>
493         ///     -or-<br/>
494         ///     <paramref name="value"/> is greater than 1.0.
495         /// </exception>
496         /// <since_tizen> 3 </since_tizen>
497         public float Volume
498         {
499             get
500             {
501                 float value = 0.0F;
502                 NativePlayer.GetVolume(Handle, out value, out value).
503                     ThrowIfFailed(this, "Failed to get the volume of the player");
504
505                 return value;
506             }
507             set
508             {
509                 if (value < 0F || 1.0F < value)
510                 {
511                     throw new ArgumentOutOfRangeException(nameof(value), value,
512                         $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
513                 }
514
515                 NativePlayer.SetVolume(Handle, value, value).
516                     ThrowIfFailed(this, "Failed to set the volume of the player");
517             }
518         }
519
520         /// <summary>
521         /// Gets or sets the audio-only state.
522         /// </summary>
523         /// <value>true if the playback is audio-only mode; otherwise, false. The default value is false.</value>
524         /// The <see cref="Player"/> must be in the <see cref="PlayerState.Ready"/>,
525         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
526         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
527         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
528         /// <since_tizen> 5 </since_tizen>
529         public bool IsAudioOnly
530         {
531             get
532             {
533                 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
534                 NativePlayer.IsAudioOnly(Handle, out var value).
535                     ThrowIfFailed(this, "Failed to get the audio-only state of the player");
536                 return value;
537             }
538             set
539             {
540                 ValidateNotDisposed();
541                 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
542                 NativePlayer.SetAudioOnly(Handle, value).
543                     ThrowIfFailed(this, "Failed to set the audio-only state of the player");
544             }
545         }
546
547         /// <summary>
548         /// Gets or sets the player's replaygain state.
549         /// </summary>
550         /// <value>If the replaygain status is true, replaygain is applied (if contents has a replaygain tag);
551         /// otherwise, the replaygain is not affected by tag and properties.</value>
552         /// <remarks>This function could be unavailable depending on the audio codec type.</remarks>
553         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
554         /// <exception cref="InvalidOperationException">
555         ///     The player is not in the valid state.
556         /// </exception>
557         /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
558         ///     -or-<br/>
559         ///     The function is not available depending on the audio codec type. (Since tizen 6.0)
560         /// </exception>
561         /// <seealso cref="AudioOffload"/>
562         /// <seealso cref="AudioCodecType"/>
563         /// <since_tizen> 5 </since_tizen>
564         public bool ReplayGain
565         {
566             get
567             {
568                 ValidateNotDisposed();
569                 AudioOffload.CheckDisabled();
570
571                 NativePlayer.IsReplayGain(Handle, out var value).
572                     ThrowIfFailed(this, "Failed to get the replaygain of the player");
573                 return value;
574             }
575             set
576             {
577                 ValidateNotDisposed();
578                 AudioOffload.CheckDisabled();
579
580                 NativePlayer.SetReplayGain(Handle, value).
581                     ThrowIfFailed(this, "Failed to set the replaygain of the player");
582             }
583         }
584
585         /// <summary>
586         /// Enables or disables controlling the pitch of audio.
587         /// Gets the status of controlling the pitch of audio.
588         /// </summary>
589         /// <value>The value indicating whether or not AudioPitch is enabled. The default is false.</value>
590         /// <remarks>This function is used for audio content only.
591         /// To set, the player must be in the <see cref="PlayerState.Idle"/> state.
592         /// This function could be unavailable depending on the audio codec type.</remarks>
593         /// <exception cref="InvalidOperationException">
594         ///     The player is not in the valid state.
595         /// </exception>
596         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
597         /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
598         ///     -or-<br/>
599         ///     The function is not available depending on the audio codec type. (Since tizen 6.0)
600         /// </exception>
601         /// <seealso cref="AudioPitch"/>
602         /// <seealso cref="AudioOffload"/>
603         /// <seealso cref="AudioCodecType"/>
604         /// <since_tizen> 6 </since_tizen>
605         public bool AudioPitchEnabled
606         {
607             get
608             {
609                 ValidateNotDisposed();
610                 AudioOffload.CheckDisabled();
611
612                 NativePlayer.IsAudioPitchEnabled(Handle, out var value).
613                     ThrowIfFailed(this, "Failed to get whether the audio pitch is enabled or not");
614                 return value;
615             }
616
617             set
618             {
619                 ValidateNotDisposed();
620                 AudioOffload.CheckDisabled();
621                 ValidatePlayerState(PlayerState.Idle);
622
623                 NativePlayer.SetAudioPitchEnabled(Handle, value).
624                     ThrowIfFailed(this, "Failed to enable the audio pitch of the player");
625             }
626         }
627
628         /// <summary>
629         /// Gets or sets the pitch of audio.
630         /// </summary>
631         /// <value>The audio stream pitch value. The default is 1.</value>
632         /// <remarks>Enabling pitch control could increase the CPU usage on some devices.
633         /// This function is used for audio content only.
634         /// This function could be unavailable depending on the audio codec type.</remarks>
635         /// <exception cref="InvalidOperationException">
636         ///     A pitch is not enabled.
637         /// </exception>
638         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
639         /// <exception cref="ArgumentOutOfRangeException">
640         ///     value is less than 0.5.
641         ///     -or-<br/>
642         ///     value is greater than 2.0.
643         /// </exception>
644         /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
645         ///     -or-<br/>
646         ///     The function is not available depending on the audio codec type. (Since tizen 6.0)
647         /// </exception>
648         /// <seealso cref="AudioPitchEnabled"/>
649         /// <seealso cref="AudioOffload"/>
650         /// <seealso cref="AudioCodecType"/>
651         /// <since_tizen> 6 </since_tizen>
652         public float AudioPitch
653         {
654             get
655             {
656                 ValidateNotDisposed();
657                 AudioOffload.CheckDisabled();
658
659                 if (AudioPitchEnabled == false)
660                 {
661                     throw new InvalidOperationException("An audio pitch is not enabled.");
662                 }
663
664                 NativePlayer.GetAudioPitch(Handle, out var value).
665                     ThrowIfFailed(this, "Failed to get the audio pitch");
666
667                 return value;
668             }
669
670             set
671             {
672                 ValidateNotDisposed();
673                 AudioOffload.CheckDisabled();
674
675                 if (AudioPitchEnabled == false)
676                 {
677                     throw new InvalidOperationException("An audio pitch is not enabled.");
678                 }
679
680                 if (value < 0.5F || 2.0F < value)
681                 {
682                     throw new ArgumentOutOfRangeException(nameof(value), value, "Valid value is 0.5 to 2.0");
683                 }
684
685                 NativePlayer.SetAudioPitch(Handle, value).ThrowIfFailed(this, "Failed to set the audio pitch");
686             }
687         }
688
689         /// <summary>
690         /// Gets or sets the default codec type of the audio decoder.
691         /// </summary>
692         /// <value>A <see cref="CodecType"/> specifies the type.
693         /// The default codec type could be different depending on the device capability.</value>
694         /// <remarks>
695         /// <para>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</para>
696         /// <para>If H/W audio codec type is not supported in some cases, S/W audio codec type could be used instead.</para>
697         /// <para>The availability could be changed depending on the codec capability.
698         /// If an application wants to use the H/W audio codec type as default,
699         /// The following functions should be called after the codec type is set. :<br/>
700         /// <see cref="AudioEffect.IsAvailable"/><br/>
701         /// <see cref="EnableExportingAudioData"/><br/>
702         /// <see cref="DisableExportingAudioData"/><br/>
703         /// <see cref="ReplayGain"/><br/>
704         /// <see cref="AudioPitch"/><br/>
705         /// <see cref="AudioPitchEnabled"/><br/></para>
706         /// </remarks>
707         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
708         /// <exception cref="ArgumentException">The value is not valid.</exception>
709         /// <exception cref="InvalidOperationException">
710         ///     The player is not in the valid state.
711         ///     -or-<br/>
712         ///     Operation failed; internal error.
713         /// </exception>
714         /// <exception cref="CodecNotSupportedException">The selected codec is not supported.</exception>
715         /// <since_tizen> 6 </since_tizen>
716         public CodecType AudioCodecType
717         {
718             get
719             {
720                 ValidateNotDisposed();
721
722                 NativePlayer.GetAudioCodecType(Handle, out var value).
723                     ThrowIfFailed(this, "Failed to get the type of the audio codec");
724
725                 return value;
726             }
727             set
728             {
729                 ValidateNotDisposed();
730                 ValidatePlayerState(PlayerState.Idle);
731
732                 ValidationUtil.ValidateEnum(typeof(CodecType), value, nameof(value));
733
734                 NativePlayer.SetAudioCodecType(Handle, value).
735                     ThrowIfFailed(this, "Failed to set the type of the audio codec");
736             }
737         }
738
739         /// <summary>
740         /// Gets or sets the codec type of the video decoder.
741         /// </summary>
742         /// <value>A <see cref="CodecType"/> specifies the type.
743         /// The default codec type could be different depending on the device capability.</value>
744         /// <remarks>
745         /// <para>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</para>
746         /// <para>If H/W video codec type is not supported in some cases, S/W video codec type could be used instead.</para>
747         /// <para>The availability could be changed depending on the codec capability.</para>
748         /// </remarks>
749         /// <exception cref="ObjectDisposedException">The player has already been disposed.</exception>
750         /// <exception cref="ArgumentException">The value is not valid.</exception>
751         /// <exception cref="InvalidOperationException">
752         ///     The player is not in the valid state.
753         ///     -or-<br/>
754         ///     Operation failed; internal error.
755         /// </exception>
756         /// <exception cref="CodecNotSupportedException">The selected codec is not supported.</exception>
757         /// <since_tizen> 11 </since_tizen>
758         public CodecType VideoCodecType
759         {
760             get
761             {
762                 ValidateNotDisposed();
763
764                 NativePlayer.GetVideoCodecType(Handle, out var value).
765                     ThrowIfFailed(this, "Failed to get the type of the video codec");
766
767                 return value;
768             }
769             set
770             {
771                 ValidateNotDisposed();
772                 ValidatePlayerState(PlayerState.Idle);
773
774                 ValidationUtil.ValidateEnum(typeof(CodecType), value, nameof(value));
775
776                 NativePlayer.SetVideoCodecType(Handle, value).
777                     ThrowIfFailed(this, "Failed to set the type of the video codec");
778             }
779         }
780
781         private SphericalVideo _sphericalVideo;
782
783         /// <summary>
784         /// Gets the spherical video settings.
785         /// </summary>
786         /// <since_tizen> 5 </since_tizen>
787         public SphericalVideo SphericalVideo
788         {
789             get
790             {
791                 if (_sphericalVideo == null)
792                 {
793                     _sphericalVideo = new SphericalVideo(this);
794                 }
795
796                 return _sphericalVideo;
797             }
798         }
799
800         private AdaptiveVariants _adaptiveVariants;
801
802         /// <summary>
803         /// Gets the adaptive variants settings.
804         /// </summary>
805         /// <since_tizen> 5 </since_tizen>
806         public AdaptiveVariants AdaptiveVariants
807         {
808             get
809             {
810                 if (_adaptiveVariants == null)
811                 {
812                     _adaptiveVariants = new AdaptiveVariants(this);
813                 }
814
815                 return _adaptiveVariants;
816             }
817         }
818
819         private AudioOffload _audioOffload;
820
821         /// <summary>
822         /// Gets the setting for audio offload.
823         /// </summary>
824         /// <since_tizen> 6 </since_tizen>
825         public AudioOffload AudioOffload
826         {
827             get
828             {
829                 if (_audioOffload == null)
830                 {
831                     _audioOffload = new AudioOffload(this);
832                 }
833
834                 return _audioOffload;
835             }
836         }
837     }
838 }