2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 using System.Threading.Tasks;
18 using System.Runtime.InteropServices;
19 using System.Diagnostics;
21 using System.Threading;
24 namespace Tizen.Multimedia
26 public partial class Player
29 /// Occurs when the playback of a media is finished.
31 /// <since_tizen> 3 </since_tizen>
32 public event EventHandler<EventArgs> PlaybackCompleted;
33 private NativePlayer.PlaybackCompletedCallback _playbackCompletedCallback;
36 /// Occurs when the playback of a media is interrupted.
39 /// If the reason is <see cref="PlaybackInterruptionReason.ResourceConflict"/>,
40 /// the player state will be one of <see cref="PlayerState.Idle"/>, <see cref="PlayerState.Ready"/>,
41 /// or <see cref="PlayerState.Paused"/>.
43 /// <seealso cref="Player.State"/>
44 /// <since_tizen> 3 </since_tizen>
45 public event EventHandler<PlaybackInterruptedEventArgs> PlaybackInterrupted;
46 private NativePlayer.PlaybackInterruptedCallback _playbackInterruptedCallback;
49 /// Occurs when any error occurs.
51 /// <remarks>The event handler will be executed on an internal thread.</remarks>
52 /// <since_tizen> 3 </since_tizen>
53 public event EventHandler<PlayerErrorOccurredEventArgs> ErrorOccurred;
54 private NativePlayer.PlaybackErrorCallback _playbackErrorCallback;
57 /// Occurs when the video stream is changed.
59 /// <remarks>The event handler will be executed on an internal thread.</remarks>
60 /// <since_tizen> 3 </since_tizen>
61 public event EventHandler<VideoStreamChangedEventArgs> VideoStreamChanged;
62 private NativePlayer.VideoStreamChangedCallback _videoStreamChangedCallback;
65 /// Occurs when the subtitle is updated.
67 /// <remarks>The event handler will be executed on an internal thread.</remarks>
68 /// <since_tizen> 3 </since_tizen>
69 public event EventHandler<SubtitleUpdatedEventArgs> SubtitleUpdated;
70 private NativePlayer.SubtitleUpdatedCallback _subtitleUpdatedCallback;
73 /// Occurs when there is a change in the buffering status of streaming.
75 /// <since_tizen> 3 </since_tizen>
76 public event EventHandler<BufferingProgressChangedEventArgs> BufferingProgressChanged;
77 private NativePlayer.BufferingProgressCallback _bufferingProgressCallback;
79 internal event EventHandler<MediaStreamBufferStatusChangedEventArgs> MediaStreamAudioBufferStatusChanged;
80 private NativePlayer.MediaStreamBufferStatusCallback _mediaStreamAudioBufferStatusChangedCallback;
82 internal event EventHandler<MediaStreamBufferStatusChangedEventArgs> MediaStreamVideoBufferStatusChanged;
83 private NativePlayer.MediaStreamBufferStatusCallback _mediaStreamVideoBufferStatusChangedCallback;
85 internal event EventHandler<MediaStreamSeekingOccurredEventArgs> MediaStreamAudioSeekingOccurred;
86 private NativePlayer.MediaStreamSeekCallback _mediaStreamAudioSeekCallback;
88 internal event EventHandler<MediaStreamSeekingOccurredEventArgs> MediaStreamVideoSeekingOccurred;
89 private NativePlayer.MediaStreamSeekCallback _mediaStreamVideoSeekCallback;
91 private bool _callbackRegistered;
93 private void RegisterEvents()
95 if (_callbackRegistered)
99 RegisterSubtitleUpdatedCallback();
100 RegisterErrorOccurredCallback();
101 RegisterPlaybackInterruptedCallback();
102 RegisterVideoStreamChangedCallback();
103 RegisterBufferingCallback();
104 RegisterMediaStreamBufferStatusCallback();
105 RegisterMediaStreamSeekCallback();
106 RegisterPlaybackCompletedCallback();
108 _callbackRegistered = true;
111 private void RegisterSubtitleUpdatedCallback()
113 _subtitleUpdatedCallback = (duration, text, _) =>
115 Log.Debug(PlayerLog.Tag, "duration : " + duration + ", text : " + text);
116 SubtitleUpdated?.Invoke(this, new SubtitleUpdatedEventArgs(duration, text));
119 NativePlayer.SetSubtitleUpdatedCb(Handle, _subtitleUpdatedCallback).
120 ThrowIfFailed("Failed to initialize the player");
123 private void RegisterPlaybackCompletedCallback()
125 _playbackCompletedCallback = _ =>
127 Log.Debug(PlayerLog.Tag, "completed callback");
128 PlaybackCompleted?.Invoke(this, EventArgs.Empty);
130 NativePlayer.SetCompletedCb(Handle, _playbackCompletedCallback).
131 ThrowIfFailed("Failed to set PlaybackCompleted");
134 private void RegisterPlaybackInterruptedCallback()
136 _playbackInterruptedCallback = (code, _) =>
138 if (!Enum.IsDefined(typeof(PlaybackInterruptionReason), code))
143 if (code == PlaybackInterruptionReason.ResourceConflict)
148 Log.Warn(PlayerLog.Tag, "interrupted reason : " + code);
149 PlaybackInterrupted?.Invoke(this, new PlaybackInterruptedEventArgs(code));
152 NativePlayer.SetInterruptedCb(Handle, _playbackInterruptedCallback).
153 ThrowIfFailed("Failed to set PlaybackInterrupted");
156 private void RegisterErrorOccurredCallback()
158 _playbackErrorCallback = (code, _) =>
160 //TODO handle service disconnected error.
161 Log.Warn(PlayerLog.Tag, "error code : " + code);
162 ErrorOccurred?.Invoke(this, new PlayerErrorOccurredEventArgs((PlayerError)code));
165 NativePlayer.SetErrorCb(Handle, _playbackErrorCallback).
166 ThrowIfFailed("Failed to set PlaybackError");
169 #region VideoFrameDecoded event
171 private EventHandler<VideoFrameDecodedEventArgs> _videoFrameDecoded;
173 private NativePlayer.VideoFrameDecodedCallback _videoFrameDecodedCallback;
176 /// Occurs when a video frame is decoded.
179 /// <para>The event handler will be executed on an internal thread.</para>
180 /// <para>The <see cref="VideoFrameDecodedEventArgs.Packet"/> in event args should be disposed after use.</para>
182 /// <feature>http://tizen.org/feature/multimedia.raw_video</feature>
183 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
184 /// <seealso cref="VideoFrameDecodedEventArgs.Packet"/>
185 /// <since_tizen> 3 </since_tizen>
186 public event EventHandler<VideoFrameDecodedEventArgs> VideoFrameDecoded
190 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
192 _videoFrameDecoded += value;
196 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
198 _videoFrameDecoded -= value;
202 private void RegisterVideoFrameDecodedCallback()
204 _videoFrameDecodedCallback = (packetHandle, _) =>
206 var handler = _videoFrameDecoded;
209 Log.Debug(PlayerLog.Tag, "packet : " + packetHandle);
211 new VideoFrameDecodedEventArgs(MediaPacket.From(packetHandle)));
215 MediaPacket.From(packetHandle).Dispose();
219 NativePlayer.SetVideoFrameDecodedCb(Handle, _videoFrameDecodedCallback).
220 ThrowIfFailed("Failed to register the VideoFrameDecoded");
224 private void RegisterVideoStreamChangedCallback()
226 _videoStreamChangedCallback = (width, height, fps, bitrate, _) =>
228 Log.Debug(PlayerLog.Tag, "height : " + height + ", width : " + width
229 + ", fps : " + fps + ", bitrate : " + bitrate);
231 VideoStreamChanged?.Invoke(this, new VideoStreamChangedEventArgs(height, width, fps, bitrate));
234 NativePlayer.SetVideoStreamChangedCb(Handle, _videoStreamChangedCallback).
235 ThrowIfFailed("Failed to set the video stream changed callback");
238 private void RegisterBufferingCallback()
240 _bufferingProgressCallback = (percent, _) =>
242 Log.Debug(PlayerLog.Tag, $"Buffering callback with percent { percent }");
243 BufferingProgressChanged?.Invoke(this, new BufferingProgressChangedEventArgs(percent));
246 NativePlayer.SetBufferingCb(Handle, _bufferingProgressCallback).
247 ThrowIfFailed("Failed to set BufferingProgress");
250 private void RegisterMediaStreamBufferStatusCallback()
252 _mediaStreamAudioBufferStatusChangedCallback = (status, _) =>
254 Debug.Assert(Enum.IsDefined(typeof(MediaStreamBufferStatus), status));
255 Log.Debug(PlayerLog.Tag, "audio buffer status : " + status);
256 MediaStreamAudioBufferStatusChanged?.Invoke(this,
257 new MediaStreamBufferStatusChangedEventArgs(status));
259 _mediaStreamVideoBufferStatusChangedCallback = (status, _) =>
261 Debug.Assert(Enum.IsDefined(typeof(MediaStreamBufferStatus), status));
262 Log.Debug(PlayerLog.Tag, "video buffer status : " + status);
263 MediaStreamVideoBufferStatusChanged?.Invoke(this,
264 new MediaStreamBufferStatusChangedEventArgs(status));
267 RegisterMediaStreamBufferStatusCallback(StreamType.Audio, _mediaStreamAudioBufferStatusChangedCallback);
268 RegisterMediaStreamBufferStatusCallback(StreamType.Video, _mediaStreamVideoBufferStatusChangedCallback);
271 private void RegisterMediaStreamBufferStatusCallback(StreamType streamType,
272 NativePlayer.MediaStreamBufferStatusCallback cb)
274 NativePlayer.SetMediaStreamBufferStatusCb(Handle, streamType, cb).
275 ThrowIfFailed("Failed to SetMediaStreamBufferStatus");
278 private void RegisterMediaStreamSeekCallback()
280 _mediaStreamAudioSeekCallback = (offset, _) =>
282 Log.Debug(PlayerLog.Tag, "audio seeking offset : " + offset);
283 MediaStreamAudioSeekingOccurred?.Invoke(this, new MediaStreamSeekingOccurredEventArgs(offset));
285 _mediaStreamVideoSeekCallback = (offset, _) =>
287 Log.Debug(PlayerLog.Tag, "video seeking offset : " + offset);
288 MediaStreamVideoSeekingOccurred?.Invoke(this, new MediaStreamSeekingOccurredEventArgs(offset));
291 RegisterMediaStreamSeekCallback(StreamType.Audio, _mediaStreamAudioSeekCallback);
292 RegisterMediaStreamSeekCallback(StreamType.Video, _mediaStreamVideoSeekCallback);
295 private void RegisterMediaStreamSeekCallback(StreamType streamType, NativePlayer.MediaStreamSeekCallback cb)
297 NativePlayer.SetMediaStreamSeekCb(Handle, streamType, cb).
298 ThrowIfFailed("Failed to SetMediaStreamSeek");