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.
19 using System.ComponentModel;
20 using System.Diagnostics;
22 namespace Tizen.Multimedia
24 public partial class Player
27 /// Occurs when the playback of a media is finished.
29 /// <since_tizen> 3 </since_tizen>
30 public event EventHandler<EventArgs> PlaybackCompleted;
31 private NativePlayer.PlaybackCompletedCallback _playbackCompletedCallback;
34 /// Occurs when the playback of a media is interrupted.
37 /// If the reason is <see cref="PlaybackInterruptionReason.ResourceConflict"/>,
38 /// the player state will be one of <see cref="PlayerState.Idle"/>, <see cref="PlayerState.Ready"/>,
39 /// or <see cref="PlayerState.Paused"/>.
41 /// <seealso cref="Player.State"/>
42 /// <since_tizen> 3 </since_tizen>
43 public event EventHandler<PlaybackInterruptedEventArgs> PlaybackInterrupted;
44 private NativePlayer.PlaybackInterruptedCallback _playbackInterruptedCallback;
47 /// Occurs when any error occurs.
49 /// <remarks>The event handler will be executed on an internal thread.</remarks>
50 /// <since_tizen> 3 </since_tizen>
51 public event EventHandler<PlayerErrorOccurredEventArgs> ErrorOccurred;
52 private NativePlayer.PlaybackErrorCallback _playbackErrorCallback;
55 /// Occurs when the video stream is changed.
57 /// <remarks>The event handler will be executed on an internal thread.</remarks>
58 /// <since_tizen> 3 </since_tizen>
59 public event EventHandler<VideoStreamChangedEventArgs> VideoStreamChanged;
60 private NativePlayer.VideoStreamChangedCallback _videoStreamChangedCallback;
63 /// Occurs when the subtitle is updated.
65 /// <remarks>The event handler will be executed on an internal thread.</remarks>
66 /// <since_tizen> 3 </since_tizen>
67 public event EventHandler<SubtitleUpdatedEventArgs> SubtitleUpdated;
68 private NativePlayer.SubtitleUpdatedCallback _subtitleUpdatedCallback;
71 /// Occurs when there is a change in the buffering status of streaming.
73 /// <since_tizen> 3 </since_tizen>
74 public event EventHandler<BufferingProgressChangedEventArgs> BufferingProgressChanged;
75 private NativePlayer.BufferingProgressCallback _bufferingProgressCallback;
77 internal event EventHandler<MediaStreamBufferStatusChangedEventArgs> MediaStreamAudioBufferStatusChanged;
78 private NativePlayer.MediaStreamBufferStatusCallback _mediaStreamAudioBufferStatusChangedCallback;
80 internal event EventHandler<MediaStreamBufferStatusChangedEventArgs> MediaStreamVideoBufferStatusChanged;
81 private NativePlayer.MediaStreamBufferStatusCallback _mediaStreamVideoBufferStatusChangedCallback;
83 internal event EventHandler<MediaStreamSeekingOccurredEventArgs> MediaStreamAudioSeekingOccurred;
84 private NativePlayer.MediaStreamSeekCallback _mediaStreamAudioSeekCallback;
86 internal event EventHandler<MediaStreamSeekingOccurredEventArgs> MediaStreamVideoSeekingOccurred;
87 private NativePlayer.MediaStreamSeekCallback _mediaStreamVideoSeekCallback;
89 private void RegisterEvents()
91 RegisterSubtitleUpdatedCallback();
92 RegisterErrorOccurredCallback();
93 RegisterPlaybackInterruptedCallback();
94 RegisterVideoStreamChangedCallback();
95 RegisterBufferingCallback();
96 RegisterMediaStreamBufferStatusCallback();
97 RegisterMediaStreamSeekCallback();
98 RegisterPlaybackCompletedCallback();
101 private void RegisterSubtitleUpdatedCallback()
103 _subtitleUpdatedCallback = (duration, text, _) =>
105 Log.Debug(PlayerLog.Tag, $"duration : {duration}, text : {text}");
106 SubtitleUpdated?.Invoke(this, new SubtitleUpdatedEventArgs(duration, text));
109 NativePlayer.SetSubtitleUpdatedCb(Handle, _subtitleUpdatedCallback).
110 ThrowIfFailed(this, "Failed to initialize the player");
113 private void RegisterPlaybackCompletedCallback()
115 _playbackCompletedCallback = _ =>
117 Log.Debug(PlayerLog.Tag, "completed callback");
118 PlaybackCompleted?.Invoke(this, EventArgs.Empty);
120 NativePlayer.SetCompletedCb(Handle, _playbackCompletedCallback).
121 ThrowIfFailed(this, "Failed to set PlaybackCompleted");
124 private void RegisterPlaybackInterruptedCallback()
126 _playbackInterruptedCallback = (code, _) =>
128 if (!Enum.IsDefined(typeof(PlaybackInterruptionReason), code))
133 if (code == PlaybackInterruptionReason.ResourceConflict)
138 Log.Warn(PlayerLog.Tag, $"interrupted reason : {code}");
139 PlaybackInterrupted?.Invoke(this, new PlaybackInterruptedEventArgs(code));
142 NativePlayer.SetInterruptedCb(Handle, _playbackInterruptedCallback).
143 ThrowIfFailed(this, "Failed to set PlaybackInterrupted");
146 private void RegisterErrorOccurredCallback()
148 _playbackErrorCallback = (code, _) =>
150 //TODO handle service disconnected error.
151 Log.Warn(PlayerLog.Tag, "error code : " + code);
152 ErrorOccurred?.Invoke(this, new PlayerErrorOccurredEventArgs((PlayerError)code));
155 NativePlayer.SetErrorCb(Handle, _playbackErrorCallback).
156 ThrowIfFailed(this, "Failed to set PlaybackError");
160 /// Raises the <see cref="ErrorOccurred"/> event.
163 /// An <see cref="PlayerErrorOccurredEventArgs"/> that contains the event data.
165 [EditorBrowsable(EditorBrowsableState.Never)]
166 protected void OnErrorOccurred(PlayerErrorOccurredEventArgs e)
168 ErrorOccurred?.Invoke(this, e);
171 #region VideoFrameDecoded event
172 private EventHandler<VideoFrameDecodedEventArgs> _videoFrameDecoded;
174 private NativePlayer.VideoFrameDecodedCallback _videoFrameDecodedCallback;
177 /// Occurs when a video frame is decoded.
180 /// <para>The event handler will be executed on an internal thread.</para>
181 /// <para>The <see cref="VideoFrameDecodedEventArgs.Packet"/> in event args should be disposed after use.</para>
183 /// <feature>http://tizen.org/feature/multimedia.raw_video</feature>
184 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
185 /// <seealso cref="VideoFrameDecodedEventArgs.Packet"/>
186 /// <since_tizen> 3 </since_tizen>
187 public event EventHandler<VideoFrameDecodedEventArgs> VideoFrameDecoded
191 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
193 _videoFrameDecoded += value;
197 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
199 _videoFrameDecoded -= value;
203 private void RegisterVideoFrameDecodedCallback()
205 _videoFrameDecodedCallback = (packetHandle, _) =>
207 var handler = _videoFrameDecoded;
210 Log.Debug(PlayerLog.Tag, "packet : " + packetHandle);
212 new VideoFrameDecodedEventArgs(MediaPacket.From(packetHandle)));
216 MediaPacket.From(packetHandle).Dispose();
220 NativePlayer.SetVideoFrameDecodedCb(Handle, _videoFrameDecodedCallback).
221 ThrowIfFailed(this, "Failed to register the VideoFrameDecoded");
225 #region AudioFrameDecoded event
227 /// Occurs when a audio frame is decoded.
230 /// <para>The event handler will be executed on an internal thread.</para>
231 /// <para>The <see cref="AudioDataDecodedEventArgs.Packet"/> in event args should be disposed after use.</para>
233 /// <seealso cref="AudioDataDecodedEventArgs.Packet"/>
234 /// <since_tizen> 6 </since_tizen>
235 public event EventHandler<AudioDataDecodedEventArgs> AudioDataDecoded;
237 private NativePlayer.AudioFrameDecodedCallback _audioFrameDecodedCallback;
240 private void RegisterVideoStreamChangedCallback()
242 _videoStreamChangedCallback = (width, height, fps, bitrate, _) =>
244 Log.Debug(PlayerLog.Tag, $"height={height}, width={width}, fps={fps}, bitrate={bitrate}");
246 VideoStreamChanged?.Invoke(this, new VideoStreamChangedEventArgs(height, width, fps, bitrate));
249 NativePlayer.SetVideoStreamChangedCb(Handle, _videoStreamChangedCallback).
250 ThrowIfFailed(this, "Failed to set the video stream changed callback");
253 private void RegisterBufferingCallback()
255 _bufferingProgressCallback = (percent, _) =>
257 Log.Debug(PlayerLog.Tag, $"Buffering callback with percent { percent }");
259 BufferingProgressChanged?.Invoke(this, new BufferingProgressChangedEventArgs(percent));
262 NativePlayer.SetBufferingCb(Handle, _bufferingProgressCallback).
263 ThrowIfFailed(this, "Failed to set BufferingProgress");
266 private void RegisterMediaStreamBufferStatusCallback()
268 _mediaStreamAudioBufferStatusChangedCallback = (status, _) =>
270 Debug.Assert(Enum.IsDefined(typeof(MediaStreamBufferStatus), status));
271 Log.Debug(PlayerLog.Tag, "audio buffer status : " + status);
273 MediaStreamAudioBufferStatusChanged?.Invoke(this,
274 new MediaStreamBufferStatusChangedEventArgs(status));
276 _mediaStreamVideoBufferStatusChangedCallback = (status, _) =>
278 Debug.Assert(Enum.IsDefined(typeof(MediaStreamBufferStatus), status));
279 Log.Debug(PlayerLog.Tag, "video buffer status : " + status);
281 MediaStreamVideoBufferStatusChanged?.Invoke(this,
282 new MediaStreamBufferStatusChangedEventArgs(status));
285 RegisterMediaStreamBufferStatusCallback(StreamType.Audio, _mediaStreamAudioBufferStatusChangedCallback);
286 RegisterMediaStreamBufferStatusCallback(StreamType.Video, _mediaStreamVideoBufferStatusChangedCallback);
289 private void RegisterMediaStreamBufferStatusCallback(StreamType streamType,
290 NativePlayer.MediaStreamBufferStatusCallback cb)
292 NativePlayer.SetMediaStreamBufferStatusCb(Handle, streamType, cb).
293 ThrowIfFailed(this, "Failed to SetMediaStreamBufferStatus");
296 private void RegisterMediaStreamSeekCallback()
298 _mediaStreamAudioSeekCallback = (offset, _) =>
300 Log.Debug(PlayerLog.Tag, "audio seeking offset : " + offset);
301 MediaStreamAudioSeekingOccurred?.Invoke(this, new MediaStreamSeekingOccurredEventArgs(offset));
303 _mediaStreamVideoSeekCallback = (offset, _) =>
305 Log.Debug(PlayerLog.Tag, "video seeking offset : " + offset);
306 MediaStreamVideoSeekingOccurred?.Invoke(this, new MediaStreamSeekingOccurredEventArgs(offset));
309 RegisterMediaStreamSeekCallback(StreamType.Audio, _mediaStreamAudioSeekCallback);
310 RegisterMediaStreamSeekCallback(StreamType.Video, _mediaStreamVideoSeekCallback);
313 private void RegisterMediaStreamSeekCallback(StreamType streamType, NativePlayer.MediaStreamSeekCallback cb)
315 NativePlayer.SetMediaStreamSeekCb(Handle, streamType, cb).
316 ThrowIfFailed(this, "Failed to SetMediaStreamSeek");