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.
18 using System.Collections.Generic;
19 using System.Diagnostics;
23 namespace Tizen.Multimedia
27 /// Provides the ability to push packets as the source of <see cref="Player"/>.
29 /// <remarks>The source must be set as a source to a player before pushing.</remarks>
30 /// <seealso cref="Player.SetSource(MediaSource)"/>
31 /// <since_tizen> 3 </since_tizen>
32 public sealed class MediaStreamSource : MediaSource
34 private readonly MediaFormat _audioMediaFormat;
35 private readonly MediaFormat _videoMediaFormat;
38 /// Gets all supported audio types.
40 /// <since_tizen> 3 </since_tizen>
41 public static IEnumerable<MediaFormatAudioMimeType> SupportedAudioTypes
45 yield return MediaFormatAudioMimeType.Aac;
50 /// Gets all supported video types.
52 /// <since_tizen> 3 </since_tizen>
53 public static IEnumerable<MediaFormatVideoMimeType> SupportedVideoTypes
57 yield return MediaFormatVideoMimeType.H264SP;
61 private Player _player;
63 private MediaStreamConfiguration CreateAudioConfiguration(AudioMediaFormat format)
70 if (!SupportedAudioTypes.Contains(format.MimeType))
72 Log.Error(PlayerLog.Tag, "The audio format is not supported : " + format.MimeType);
73 throw new ArgumentException($"The audio format is not supported, Type : {format.MimeType}.");
76 return new MediaStreamConfiguration(this, StreamType.Audio);
79 private MediaStreamConfiguration CreateVideoConfiguration(VideoMediaFormat format)
86 if (!SupportedVideoTypes.Contains(format.MimeType))
88 Log.Error(PlayerLog.Tag, "The video format is not supported : " + format.MimeType);
89 throw new ArgumentException($"The video format is not supported, Type : {format.MimeType}.");
92 return new MediaStreamConfiguration(this, StreamType.Video);
97 /// Initializes a new instance of the MediaStreamSource class
98 /// with the specified <see cref="AudioMediaFormat"/> and <see cref="VideoMediaFormat"/>.
100 /// <param name="audioMediaFormat">The <see cref="AudioMediaFormat"/> for this source.</param>
101 /// <param name="videoMediaFormat">The <see cref="VideoMediaFormat"/> for this source.</param>
102 /// <remarks>AAC and H.264 are supported.</remarks>
103 /// <exception cref="ArgumentNullException">Both <paramref name="audioMediaFormat"/> and <paramref name="videoMediaFormat"/> are null.</exception>
104 /// <exception cref="ArgumentException">
105 /// <paramref name="audioMediaFormat"/> is not supported.<br/>
107 /// <paramref name="videoMediaFormat"/> is not supported.
109 /// <seealso cref="SupportedAudioTypes"/>
110 /// <seealso cref="SupportedVideoTypes"/>
111 /// <since_tizen> 3 </since_tizen>
112 public MediaStreamSource(AudioMediaFormat audioMediaFormat, VideoMediaFormat videoMediaFormat)
114 if (audioMediaFormat == null && videoMediaFormat == null)
116 throw new ArgumentNullException(nameof(audioMediaFormat) + " and " + nameof(videoMediaFormat));
119 _audioMediaFormat = audioMediaFormat;
120 _videoMediaFormat = videoMediaFormat;
122 AudioConfiguration = CreateAudioConfiguration(audioMediaFormat);
123 VideoConfiguration = CreateVideoConfiguration(videoMediaFormat);
127 /// Initializes a new instance of the MediaStreamSource class with the specified <see cref="AudioMediaFormat"/>.
129 /// <param name="audioMediaFormat">The <see cref="AudioMediaFormat"/> for this source.</param>
130 /// <remarks>AAC is supported.</remarks>
131 /// <exception cref="ArgumentNullException"><paramref name="audioMediaFormat"/> is null.</exception>
132 /// <exception cref="ArgumentException"><paramref name="audioMediaFormat"/> is not supported.</exception>
133 /// <seealso cref="SupportedAudioTypes"/>
134 /// <since_tizen> 3 </since_tizen>
135 public MediaStreamSource(AudioMediaFormat audioMediaFormat)
137 if (audioMediaFormat == null)
139 throw new ArgumentNullException(nameof(audioMediaFormat));
142 _audioMediaFormat = audioMediaFormat;
144 AudioConfiguration = CreateAudioConfiguration(audioMediaFormat);
147 /// Initializes a new instance of the MediaStreamSource class with the specified <see cref="VideoMediaFormat"/>.
149 /// <remarks>H.264 is supported.</remarks>
150 /// <param name="videoMediaFormat">The <see cref="VideoMediaFormat"/> for this source.</param>
151 /// <exception cref="ArgumentNullException"><paramref name="videoMediaFormat"/> is null.</exception>
152 /// <exception cref="ArgumentException"><paramref name="videoMediaFormat"/> is not supported.</exception>
153 /// <seealso cref="SupportedVideoTypes"/>
154 /// <since_tizen> 3 </since_tizen>
155 public MediaStreamSource(VideoMediaFormat videoMediaFormat)
157 if (videoMediaFormat == null)
159 throw new ArgumentNullException(nameof(videoMediaFormat));
162 _videoMediaFormat = videoMediaFormat;
164 VideoConfiguration = CreateVideoConfiguration(videoMediaFormat);
168 /// Gets the audio configuration, or null if no AudioMediaFormat is specified in the constructor.
170 /// <since_tizen> 3 </since_tizen>
171 public MediaStreamConfiguration AudioConfiguration { get; }
174 /// Gets the video configuration, or null if no VideoMediaFormat is specified in the constructor.
176 /// <since_tizen> 3 </since_tizen>
177 public MediaStreamConfiguration VideoConfiguration { get; }
180 /// Pushes elementary stream to decode audio or video.
182 /// <remarks>This source must be set as a source to a player and the player must be in the <see cref="PlayerState.Ready"/>,
183 /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.</remarks>
184 /// <param name="packet">The <see cref="MediaPacket"/> to decode.</param>
185 /// <exception cref="InvalidOperationException">
186 /// This source is not set as a source to a player.<br/>
188 /// The player is not in the valid state.
190 /// <exception cref="ArgumentNullException"><paramref name="packet"/> is null.</exception>
191 /// <exception cref="ObjectDisposedException"><paramref name="packet"/> has been disposed of.</exception>
192 /// <exception cref="ArgumentException">
193 /// <paramref name="packet"/> is neither video nor audio type.<br/>
195 /// The format of packet is not matched with the specified format in the constructor.
197 /// <exception cref="NoBufferSpaceException">The internal buffer has reached its limits.</exception>
198 /// <seealso cref="Player.SetSource(MediaSource)"/>
199 /// <seealso cref="MediaStreamConfiguration.BufferMaxSize"/>
200 /// <seealso cref="MediaPacket"/>
201 /// <since_tizen> 3 </since_tizen>
202 public void Push(MediaPacket packet)
206 Log.Error(PlayerLog.Tag, "The source is not set as a source to a player yet.");
207 throw new InvalidOperationException("The source is not set as a source to a player yet.");
211 Log.Error(PlayerLog.Tag, "packet is null");
212 throw new ArgumentNullException(nameof(packet));
214 if (packet.IsDisposed)
216 Log.Error(PlayerLog.Tag, "packet is disposed");
217 throw new ObjectDisposedException(nameof(packet));
220 if (packet.Format.Type == MediaFormatType.Text || packet.Format.Type == MediaFormatType.Container)
222 Log.Error(PlayerLog.Tag, "The format of the packet is invalid : " + packet.Format.Type);
223 throw new ArgumentException($"The format of the packet is invalid : { packet.Format.Type }.");
226 if (!packet.Format.Equals(_audioMediaFormat) && !packet.Format.Equals(_videoMediaFormat))
228 Log.Error(PlayerLog.Tag, "The format of the packet is invalid : Unmatched format.");
229 throw new ArgumentException($"The format of the packet is invalid : Unmatched format.");
232 if (packet.Format.Type == MediaFormatType.Video && _videoMediaFormat == null)
234 Log.Error(PlayerLog.Tag, "Video is not configured with the current source.");
235 throw new ArgumentException("Video is not configured with the current source.");
237 if (packet.Format.Type == MediaFormatType.Audio && _audioMediaFormat == null)
239 Log.Error(PlayerLog.Tag, "Audio is not configured with the current source.");
240 throw new ArgumentException("Audio is not configured with the current source.");
243 _player.ValidatePlayerState(PlayerState.Paused, PlayerState.Playing, PlayerState.Ready);
245 NativePlayer.PushMediaStream(_player.Handle, packet.GetHandle()).
246 ThrowIfFailed(_player, "Failed to push the packet to the player");
249 private void SetMediaStreamInfo(StreamType streamType, MediaFormat mediaFormat)
251 if (mediaFormat == null)
253 Log.Error(PlayerLog.Tag, "invalid media format");
257 IntPtr ptr = IntPtr.Zero;
261 ptr = mediaFormat.AsNativeHandle();
263 NativePlayer.SetMediaStreamInfo(_player.Handle, streamType, ptr).
264 ThrowIfFailed(_player, "Failed to set the media stream info");
268 MediaFormat.ReleaseNativeHandle(ptr);
272 internal override void OnAttached(Player player)
274 Debug.Assert(player != null);
278 Log.Error(PlayerLog.Tag, "The source is has already been assigned to another player.");
279 throw new InvalidOperationException("The source is has already been assigned to another player.");
282 AudioConfiguration?.OnPlayerSet(player);
283 VideoConfiguration?.OnPlayerSet(player);
287 SetMediaStreamInfo(StreamType.Audio, _audioMediaFormat);
288 SetMediaStreamInfo(StreamType.Video, _videoMediaFormat);
291 internal override void OnDetached(Player player)
293 base.OnDetached(player);
295 AudioConfiguration?.OnPlayerUnset(player);
296 VideoConfiguration?.OnPlayerUnset(player);
302 /// Gets the <see cref="Player"/> that this source is assigned to as a source, or null if this source is not assigned.
304 /// <seealso cref="Player.SetSource(MediaSource)"/>
305 /// <since_tizen> 3 </since_tizen>
306 public Player Player => _player;