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.
38 /// <since_tizen> 3 </since_tizen>
39 public event EventHandler<PlaybackInterruptedEventArgs> PlaybackInterrupted;
40 private NativePlayer.PlaybackInterruptedCallback _playbackInterruptedCallback;
43 /// Occurs when any error occurs.
45 /// <remarks>The event handler will be executed on an internal thread.</remarks>
46 /// <since_tizen> 3 </since_tizen>
47 public event EventHandler<PlayerErrorOccurredEventArgs> ErrorOccurred;
48 private NativePlayer.PlaybackErrorCallback _playbackErrorCallback;
51 /// Occurs when the video stream is changed.
53 /// <remarks>The event handler will be executed on an internal thread.</remarks>
54 /// <since_tizen> 3 </since_tizen>
55 public event EventHandler<VideoStreamChangedEventArgs> VideoStreamChanged;
56 private NativePlayer.VideoStreamChangedCallback _videoStreamChangedCallback;
59 /// Occurs when the subtitle is updated.
61 /// <remarks>The event handler will be executed on an internal thread.</remarks>
62 /// <since_tizen> 3 </since_tizen>
63 public event EventHandler<SubtitleUpdatedEventArgs> SubtitleUpdated;
64 private NativePlayer.SubtitleUpdatedCallback _subtitleUpdatedCallback;
67 /// Occurs when there is a change in the buffering status of streaming.
69 /// <since_tizen> 3 </since_tizen>
70 public event EventHandler<BufferingProgressChangedEventArgs> BufferingProgressChanged;
71 private NativePlayer.BufferingProgressCallback _bufferingProgressCallback;
73 internal event EventHandler<MediaStreamBufferStatusChangedEventArgs> MediaStreamAudioBufferStatusChanged;
74 private NativePlayer.MediaStreamBufferStatusCallback _mediaStreamAudioBufferStatusChangedCallback;
76 internal event EventHandler<MediaStreamBufferStatusChangedEventArgs> MediaStreamVideoBufferStatusChanged;
77 private NativePlayer.MediaStreamBufferStatusCallback _mediaStreamVideoBufferStatusChangedCallback;
79 internal event EventHandler<MediaStreamSeekingOccurredEventArgs> MediaStreamAudioSeekingOccurred;
80 private NativePlayer.MediaStreamSeekCallback _mediaStreamAudioSeekCallback;
82 internal event EventHandler<MediaStreamSeekingOccurredEventArgs> MediaStreamVideoSeekingOccurred;
83 private NativePlayer.MediaStreamSeekCallback _mediaStreamVideoSeekCallback;
85 private bool _callbackRegistered;
87 private void RegisterEvents()
89 if (_callbackRegistered)
93 RegisterSubtitleUpdatedCallback();
94 RegisterErrorOccurredCallback();
95 RegisterPlaybackInterruptedCallback();
96 RegisterVideoStreamChangedCallback();
97 RegisterBufferingCallback();
98 RegisterMediaStreamBufferStatusCallback();
99 RegisterMediaStreamSeekCallback();
100 RegisterPlaybackCompletedCallback();
102 _callbackRegistered = true;
105 private void RegisterSubtitleUpdatedCallback()
107 _subtitleUpdatedCallback = (duration, text, _) =>
109 Log.Debug(PlayerLog.Tag, "duration : " + duration + ", text : " + text);
110 SubtitleUpdated?.Invoke(this, new SubtitleUpdatedEventArgs(duration, text));
113 NativePlayer.SetSubtitleUpdatedCb(Handle, _subtitleUpdatedCallback).
114 ThrowIfFailed("Failed to initialize the player");
117 private void RegisterPlaybackCompletedCallback()
119 _playbackCompletedCallback = _ =>
121 Log.Debug(PlayerLog.Tag, "completed callback");
122 PlaybackCompleted?.Invoke(this, EventArgs.Empty);
124 NativePlayer.SetCompletedCb(Handle, _playbackCompletedCallback).
125 ThrowIfFailed("Failed to set PlaybackCompleted");
128 private void RegisterPlaybackInterruptedCallback()
130 _playbackInterruptedCallback = (code, _) =>
132 if (!Enum.IsDefined(typeof(PlaybackInterruptionReason), code))
137 if (code == PlaybackInterruptionReason.ResourceConflict)
142 Log.Warn(PlayerLog.Tag, "interrupted reason : " + code);
143 PlaybackInterrupted?.Invoke(this, new PlaybackInterruptedEventArgs(code));
146 NativePlayer.SetInterruptedCb(Handle, _playbackInterruptedCallback).
147 ThrowIfFailed("Failed to set PlaybackInterrupted");
150 private void RegisterErrorOccurredCallback()
152 _playbackErrorCallback = (code, _) =>
154 //TODO handle service disconnected error.
155 Log.Warn(PlayerLog.Tag, "error code : " + code);
156 ErrorOccurred?.Invoke(this, new PlayerErrorOccurredEventArgs((PlayerError)code));
159 NativePlayer.SetErrorCb(Handle, _playbackErrorCallback).
160 ThrowIfFailed("Failed to set PlaybackError");
163 #region VideoFrameDecoded event
165 private EventHandler<VideoFrameDecodedEventArgs> _videoFrameDecoded;
167 private NativePlayer.VideoFrameDecodedCallback _videoFrameDecodedCallback;
170 /// Occurs when a video frame is decoded.
173 /// <para>The event handler will be executed on an internal thread.</para>
174 /// <para>The <see cref="VideoFrameDecodedEventArgs.Packet"/> in event args should be disposed after use.</para>
176 /// <feature>http://tizen.org/feature/multimedia.raw_video</feature>
177 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
178 /// <seealso cref="VideoFrameDecodedEventArgs.Packet"/>
179 /// <since_tizen> 3 </since_tizen>
180 public event EventHandler<VideoFrameDecodedEventArgs> VideoFrameDecoded
184 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
186 _videoFrameDecoded += value;
190 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
192 _videoFrameDecoded -= value;
196 private void RegisterVideoFrameDecodedCallback()
198 _videoFrameDecodedCallback = (packetHandle, _) =>
200 var handler = _videoFrameDecoded;
203 Log.Debug(PlayerLog.Tag, "packet : " + packetHandle);
205 new VideoFrameDecodedEventArgs(MediaPacket.From(packetHandle)));
209 MediaPacket.From(packetHandle).Dispose();
213 NativePlayer.SetVideoFrameDecodedCb(Handle, _videoFrameDecodedCallback).
214 ThrowIfFailed("Failed to register the VideoFrameDecoded");
218 private void RegisterVideoStreamChangedCallback()
220 _videoStreamChangedCallback = (width, height, fps, bitrate, _) =>
222 Log.Debug(PlayerLog.Tag, "height : " + height + ", width : " + width
223 + ", fps : " + fps + ", bitrate : " + bitrate);
225 VideoStreamChanged?.Invoke(this, new VideoStreamChangedEventArgs(height, width, fps, bitrate));
228 NativePlayer.SetVideoStreamChangedCb(Handle, _videoStreamChangedCallback).
229 ThrowIfFailed("Failed to set the video stream changed callback");
232 private void RegisterBufferingCallback()
234 _bufferingProgressCallback = (percent, _) =>
236 Log.Debug(PlayerLog.Tag, $"Buffering callback with percent { percent }");
237 BufferingProgressChanged?.Invoke(this, new BufferingProgressChangedEventArgs(percent));
240 NativePlayer.SetBufferingCb(Handle, _bufferingProgressCallback).
241 ThrowIfFailed("Failed to set BufferingProgress");
244 private void RegisterMediaStreamBufferStatusCallback()
246 _mediaStreamAudioBufferStatusChangedCallback = (status, _) =>
248 Debug.Assert(Enum.IsDefined(typeof(MediaStreamBufferStatus), status));
249 Log.Debug(PlayerLog.Tag, "audio buffer status : " + status);
250 MediaStreamAudioBufferStatusChanged?.Invoke(this,
251 new MediaStreamBufferStatusChangedEventArgs(status));
253 _mediaStreamVideoBufferStatusChangedCallback = (status, _) =>
255 Debug.Assert(Enum.IsDefined(typeof(MediaStreamBufferStatus), status));
256 Log.Debug(PlayerLog.Tag, "video buffer status : " + status);
257 MediaStreamVideoBufferStatusChanged?.Invoke(this,
258 new MediaStreamBufferStatusChangedEventArgs(status));
261 RegisterMediaStreamBufferStatusCallback(StreamType.Audio, _mediaStreamAudioBufferStatusChangedCallback);
262 RegisterMediaStreamBufferStatusCallback(StreamType.Video, _mediaStreamVideoBufferStatusChangedCallback);
265 private void RegisterMediaStreamBufferStatusCallback(StreamType streamType,
266 NativePlayer.MediaStreamBufferStatusCallback cb)
268 NativePlayer.SetMediaStreamBufferStatusCb(Handle, streamType, cb).
269 ThrowIfFailed("Failed to SetMediaStreamBufferStatus");
272 private void RegisterMediaStreamSeekCallback()
274 _mediaStreamAudioSeekCallback = (offset, _) =>
276 Log.Debug(PlayerLog.Tag, "audio seeking offset : " + offset);
277 MediaStreamAudioSeekingOccurred?.Invoke(this, new MediaStreamSeekingOccurredEventArgs(offset));
279 _mediaStreamVideoSeekCallback = (offset, _) =>
281 Log.Debug(PlayerLog.Tag, "video seeking offset : " + offset);
282 MediaStreamVideoSeekingOccurred?.Invoke(this, new MediaStreamSeekingOccurredEventArgs(offset));
285 RegisterMediaStreamSeekCallback(StreamType.Audio, _mediaStreamAudioSeekCallback);
286 RegisterMediaStreamSeekCallback(StreamType.Video, _mediaStreamVideoSeekCallback);
289 private void RegisterMediaStreamSeekCallback(StreamType streamType, NativePlayer.MediaStreamSeekCallback cb)
291 NativePlayer.SetMediaStreamSeekCb(Handle, streamType, cb).
292 ThrowIfFailed("Failed to SetMediaStreamSeek");