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 public sealed class MediaStreamSource : MediaSource
33 private readonly MediaFormat _audioMediaFormat;
34 private readonly MediaFormat _videoMediaFormat;
37 /// Gets all supported audio types.
39 public static IEnumerable<MediaFormatAudioMimeType> SupportedAudioTypes
43 yield return MediaFormatAudioMimeType.Aac;
48 /// Gets all supported video types.
50 public static IEnumerable<MediaFormatVideoMimeType> SupportedVideoTypes
54 yield return MediaFormatVideoMimeType.H264SP;
58 private Player _player;
60 private MediaStreamConfiguration CreateAudioConfiguration(AudioMediaFormat format)
67 if (!SupportedAudioTypes.Contains(format.MimeType))
69 Log.Error(PlayerLog.Tag, "The audio format is not supported : " + format.MimeType);
70 throw new ArgumentException($"The audio format is not supported, Type : {format.MimeType}.");
73 return new MediaStreamConfiguration(this, StreamType.Audio);
76 private MediaStreamConfiguration CreateVideoConfiguration(VideoMediaFormat format)
83 if (!SupportedVideoTypes.Contains(format.MimeType))
85 Log.Error(PlayerLog.Tag, "The video format is not supported : " + format.MimeType);
86 throw new ArgumentException($"The video format is not supported, Type : {format.MimeType}.");
89 return new MediaStreamConfiguration(this, StreamType.Video);
94 /// Initializes a new instance of the MediaStreamSource class
95 /// with the specified <see cref="AudioMediaFormat"/> and <see cref="VideoMediaFormat"/>.
97 /// <param name="audioMediaFormat">The <see cref="AudioMediaFormat"/> for this source.</param>
98 /// <param name="videoMediaFormat">The <see cref="VideoMediaFormat"/> for this source.</param>
99 /// <remarks>AAC and H.264 are supported.</remarks>
100 /// <exception cref="ArgumentNullException">Both <paramref name="audioMediaFormat"/> and <paramref name="videoMediaFormat"/> are null.</exception>
101 /// <exception cref="ArgumentException">
102 /// <paramref name="audioMediaFormat"/> is not supported.\n
104 /// <paramref name="videoMediaFormat"/> is not supported.\n
106 /// <seealso cref="SupportedAudioTypes"/>
107 /// <seealso cref="SupportedVideoTypes"/>
108 public MediaStreamSource(AudioMediaFormat audioMediaFormat, VideoMediaFormat videoMediaFormat)
110 if (audioMediaFormat == null && videoMediaFormat == null)
112 throw new ArgumentNullException(nameof(audioMediaFormat) + " and " + nameof(videoMediaFormat));
115 _audioMediaFormat = audioMediaFormat;
116 _videoMediaFormat = videoMediaFormat;
118 AudioConfiguration = CreateAudioConfiguration(audioMediaFormat);
119 VideoConfiguration = CreateVideoConfiguration(videoMediaFormat);
123 /// Initializes a new instance of the MediaStreamSource class with the specified <see cref="AudioMediaFormat"/>.
125 /// <param name="audioMediaFormat">The <see cref="AudioMediaFormat"/> for this source.</param>
126 /// <remarks>AAC is supported.</remarks>
127 /// <exception cref="ArgumentNullException"><paramref name="audioMediaFormat"/> is null.</exception>
128 /// <exception cref="ArgumentException"><paramref name="audioMediaFormat"/> is not supported.</exception>
129 /// <seealso cref="SupportedAudioTypes"/>
130 public MediaStreamSource(AudioMediaFormat audioMediaFormat)
132 if (audioMediaFormat == null)
134 throw new ArgumentNullException(nameof(audioMediaFormat));
137 _audioMediaFormat = audioMediaFormat;
139 AudioConfiguration = CreateAudioConfiguration(audioMediaFormat);
142 /// Initializes a new instance of the MediaStreamSource class with the specified <see cref="VideoMediaFormat"/>.
144 /// <remarks>H.264 is supported.</remarks>
145 /// <param name="videoMediaFormat">The <see cref="VideoMediaFormat"/> for this source.</param>
146 /// <exception cref="ArgumentNullException"><paramref name="videoMediaFormat"/> is null.</exception>
147 /// <exception cref="ArgumentException"><paramref name="videoMediaFormat"/> is not supported.</exception>
148 /// <seealso cref="SupportedVideoTypes"/>
149 public MediaStreamSource(VideoMediaFormat videoMediaFormat)
151 if (videoMediaFormat == null)
153 throw new ArgumentNullException(nameof(videoMediaFormat));
156 _videoMediaFormat = videoMediaFormat;
158 VideoConfiguration = CreateVideoConfiguration(videoMediaFormat);
162 /// Gets the audio configuration, or null if no AudioMediaFormat is specified in the constructor.
164 public MediaStreamConfiguration AudioConfiguration { get; }
167 /// Gets the video configuration, or null if no VideoMediaFormat is specified in the constructor.
169 public MediaStreamConfiguration VideoConfiguration { get; }
172 /// Pushes elementary stream to decode audio or video.
174 /// <remarks>This source must be set as a source to a player and the player must be in the <see cref="PlayerState.Ready"/>,
175 /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.</remarks>
176 /// <param name="packet">The <see cref="MediaPacket"/> to decode.</param>
177 /// <exception cref="InvalidOperationException">
178 /// This source is not set as a source to a player.\n
180 /// The player is not in the valid state.
182 /// <exception cref="ArgumentNullException"><paramref name="packet"/> is null.</exception>
183 /// <exception cref="ObjectDisposedException"><paramref name="packet"/> has been disposed of.</exception>
184 /// <exception cref="ArgumentException">
185 /// <paramref name="packet"/> is neither video nor audio type.\n
187 /// The format of packet is not matched with the specified format in the constructor.
189 /// <exception cref="NoBufferSpaceException">The internal buffer has reached its limits.</exception>
190 /// <seealso cref="Player.SetSource(MediaSource)"/>
191 /// <seealso cref="MediaStreamConfiguration.BufferMaxSize"/>
192 /// <seealso cref="MediaPacket"/>
193 public void Push(MediaPacket packet)
197 Log.Error(PlayerLog.Tag, "The source is not set as a source to a player yet.");
198 throw new InvalidOperationException("The source is not set as a source to a player yet.");
202 Log.Error(PlayerLog.Tag, "packet is null");
203 throw new ArgumentNullException(nameof(packet));
205 if (packet.IsDisposed)
207 Log.Error(PlayerLog.Tag, "packet is disposed");
208 throw new ObjectDisposedException(nameof(packet));
211 if (packet.Format.Type == MediaFormatType.Text || packet.Format.Type == MediaFormatType.Container)
213 Log.Error(PlayerLog.Tag, "The format of the packet is invalid : " + packet.Format.Type);
214 throw new ArgumentException($"The format of the packet is invalid : { packet.Format.Type }.");
217 if (!packet.Format.Equals(_audioMediaFormat) && !packet.Format.Equals(_videoMediaFormat))
219 Log.Error(PlayerLog.Tag, "The format of the packet is invalid : Unmatched format.");
220 throw new ArgumentException($"The format of the packet is invalid : Unmatched format.");
223 if (packet.Format.Type == MediaFormatType.Video && _videoMediaFormat == null)
225 Log.Error(PlayerLog.Tag, "Video is not configured with the current source.");
226 throw new ArgumentException("Video is not configured with the current source.");
228 if (packet.Format.Type == MediaFormatType.Audio && _audioMediaFormat == null)
230 Log.Error(PlayerLog.Tag, "Audio is not configured with the current source.");
231 throw new ArgumentException("Audio is not configured with the current source.");
234 _player.ValidatePlayerState(PlayerState.Paused, PlayerState.Playing, PlayerState.Ready);
236 NativePlayer.PushMediaStream(_player.Handle, packet.GetHandle()).
237 ThrowIfFailed("Failed to push the packet to the player");
240 private void SetMediaStreamInfo(StreamType streamType, MediaFormat mediaFormat)
242 if (mediaFormat == null)
244 Log.Error(PlayerLog.Tag, "invalid media format");
248 IntPtr ptr = IntPtr.Zero;
252 ptr = mediaFormat.AsNativeHandle();
253 NativePlayer.SetMediaStreamInfo(_player.Handle, (int)streamType, ptr).
254 ThrowIfFailed("Failed to set the media stream info");
258 MediaFormat.ReleaseNativeHandle(ptr);
262 internal override void OnAttached(Player player)
264 Debug.Assert(player != null);
268 Log.Error(PlayerLog.Tag, "The source is has already been assigned to another player.");
269 throw new InvalidOperationException("The source is has already been assigned to another player.");
272 AudioConfiguration?.OnPlayerSet(player);
273 VideoConfiguration?.OnPlayerSet(player);
277 SetMediaStreamInfo(StreamType.Audio, _audioMediaFormat);
278 SetMediaStreamInfo(StreamType.Video, _videoMediaFormat);
281 internal override void OnDetached(Player player)
283 base.OnDetached(player);
285 AudioConfiguration?.OnPlayerUnset(player);
286 VideoConfiguration?.OnPlayerUnset(player);
292 /// Gets the <see cref="Player"/> that this source is assigned to as a source, or null if this source is not assigned.
294 /// <seealso cref="Player.SetSource(MediaSource)"/>
295 public Player Player => _player;