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.Collections.Generic;
18 using System.Diagnostics;
22 namespace Tizen.Multimedia
26 /// Provides the ability to push packets as the source of <see cref="Player"/>
28 /// <remarks>The source must be set as a source to a player before pushing.</remarks>
29 /// <seealso cref="Player.SetSource(MediaSource)"/>
30 public sealed class MediaStreamSource : MediaSource
32 private readonly MediaFormat _audioMediaFormat;
33 private readonly MediaFormat _videoMediaFormat;
36 /// Gets all supported audio types.
38 public static IEnumerable<MediaFormatAudioMimeType> SupportedAudioTypes
42 yield return MediaFormatAudioMimeType.Aac;
47 /// Gets all supported video types.
49 public static IEnumerable<MediaFormatVideoMimeType> SupportedVideoTypes
53 yield return MediaFormatVideoMimeType.H264SP;
57 private Player _player;
59 private MediaStreamConfiguration CreateAudioConfiguration(AudioMediaFormat format)
66 if (!SupportedAudioTypes.Contains(format.MimeType))
68 Log.Error(PlayerLog.Tag, "The audio format is not supported : " + format.MimeType);
69 throw new ArgumentException($"The audio format is not supported, Type : {format.MimeType}.");
72 return new MediaStreamConfiguration(this, StreamType.Audio);
75 private MediaStreamConfiguration CreateVideoConfiguration(VideoMediaFormat format)
82 if (!SupportedVideoTypes.Contains(format.MimeType))
84 Log.Error(PlayerLog.Tag, "The video format is not supported : " + format.MimeType);
85 throw new ArgumentException($"The video format is not supported, Type : {format.MimeType}.");
88 return new MediaStreamConfiguration(this, StreamType.Video);
93 /// Initialize a new instance of the MediaStreamSource class
94 /// with the specified <see cref="AudioMediaFormat"/> and <see cref="VideoMediaFormat"/>.
96 /// <param name="audioMediaFormat">The <see cref="AudioMediaFormat"/> for this source.</param>
97 /// <param name="videoMediaFormat">The <see cref="VideoMediaFormat"/> for this source.</param>
98 /// <remarks>AAC and H.264 are supported.</remarks>
99 /// <exception cref="ArgumentNullException">Both <paramref name="audioMediaFormat"/> and <paramref name="videoMediaFormat"/> are null.</exception>
100 /// <exception cref="ArgumentException">
101 /// <paramref name="audioMediaFormat"/> is not supported.\n
103 /// <paramref name="videoMediaFormat"/> is not supported.\n
105 /// <seealso cref="SupportedAudioTypes"/>
106 /// <seealso cref="SupportedVideoTypes"/>
107 public MediaStreamSource(AudioMediaFormat audioMediaFormat, VideoMediaFormat videoMediaFormat)
109 if (audioMediaFormat == null && videoMediaFormat == null)
111 throw new ArgumentNullException(nameof(audioMediaFormat) + " and " + nameof(videoMediaFormat));
114 _audioMediaFormat = audioMediaFormat;
115 _videoMediaFormat = videoMediaFormat;
117 AudioConfiguration = CreateAudioConfiguration(audioMediaFormat);
118 VideoConfiguration = CreateVideoConfiguration(videoMediaFormat);
122 /// Initialize a new instance of the MediaStreamSource class with the specified <see cref="AudioMediaFormat"/>.
124 /// <param name="audioMediaFormat">The <see cref="AudioMediaFormat"/> for this source.</param>
125 /// <remarks>AAC is supported.</remarks>
126 /// <exception cref="ArgumentNullException"><paramref name="audioMediaFormat"/> is null.</exception>
127 /// <exception cref="ArgumentException"><paramref name="audioMediaFormat"/> is not supported.</exception>
128 /// <seealso cref="SupportedAudioTypes"/>
129 public MediaStreamSource(AudioMediaFormat audioMediaFormat)
131 if (audioMediaFormat == null)
133 throw new ArgumentNullException(nameof(audioMediaFormat));
136 _audioMediaFormat = audioMediaFormat;
138 AudioConfiguration = CreateAudioConfiguration(audioMediaFormat);
141 /// Initialize a new instance of the MediaStreamSource class with the specified <see cref="VideoMediaFormat"/>.
143 /// <remarks>H.264 can is supported.</remarks>
144 /// <param name="videoMediaFormat">The <see cref="VideoMediaFormat"/> for this source.</param>
145 /// <exception cref="ArgumentNullException"><paramref name="videoMediaFormat"/> is null.</exception>
146 /// <exception cref="ArgumentException"><paramref name="videoMediaFormat"/> is not supported.</exception>
147 /// <seealso cref="SupportedVideoTypes"/>
148 public MediaStreamSource(VideoMediaFormat videoMediaFormat)
150 if (videoMediaFormat == null)
152 throw new ArgumentNullException(nameof(videoMediaFormat));
155 _videoMediaFormat = videoMediaFormat;
157 VideoConfiguration = CreateVideoConfiguration(videoMediaFormat);
161 /// Gets the audio configuration or null if no AudioMediaFormat is specified in the constructor.
163 public MediaStreamConfiguration AudioConfiguration { get; }
166 /// Gets the video configuration or null if no VideoMediaFormat is specified in the constructor.
168 public MediaStreamConfiguration VideoConfiguration { get; }
171 /// Pushes elementary stream to decode audio or video.
173 /// <remarks>This source must be set as a source to a player and the player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.</remarks>
174 /// <param name="packet">The <see cref="MediaPacket"/> to decode.</param>
175 /// <exception cref="InvalidOperationException">
176 /// This source is not set as a source to a player.\n
178 /// The player is not in the valid state.
180 /// <exception cref="ArgumentNullException">packet is null.</exception>
181 /// <exception cref="ObjectDisposedException">packet has been disposed.</exception>
182 /// <exception cref="ArgumentException">
183 /// <paramref name="packet"/> is neither video nor audio type.\n
185 /// The format of packet is not matched with the specified format in the constructor.
187 /// <exception cref="NoBufferSpaceException">the internal buffer reaches limits.</exception>
188 /// <seealso cref="Player.SetSource(MediaSource)"/>
189 /// <seealso cref="MediaStreamConfiguration.BufferMaxSize"/>
190 /// <seealso cref="MediaPacket"/>
191 public void Push(MediaPacket packet)
195 Log.Error(PlayerLog.Tag, "The source is not set as a source to a player yet.");
196 throw new InvalidOperationException("The source is not set as a source to a player yet.");
200 Log.Error(PlayerLog.Tag, "packet is null");
201 throw new ArgumentNullException(nameof(packet));
203 if (packet.IsDisposed)
205 Log.Error(PlayerLog.Tag, "packet is disposed");
206 throw new ObjectDisposedException(nameof(packet));
209 if (packet.Format.Type == MediaFormatType.Text || packet.Format.Type == MediaFormatType.Container)
211 Log.Error(PlayerLog.Tag, "The format of the packet is invalid : " + packet.Format.Type);
212 throw new ArgumentException($"The format of the packet is invalid : { packet.Format.Type }.");
215 if (!packet.Format.Equals(_audioMediaFormat) && !packet.Format.Equals(_videoMediaFormat))
217 Log.Error(PlayerLog.Tag, "The format of the packet is invalid : Unmatched format.");
218 throw new ArgumentException($"The format of the packet is invalid : Unmatched format.");
221 if (packet.Format.Type == MediaFormatType.Video && _videoMediaFormat == null)
223 Log.Error(PlayerLog.Tag, "Video is not configured with the current source.");
224 throw new ArgumentException("Video is not configured with the current source.");
226 if (packet.Format.Type == MediaFormatType.Audio && _audioMediaFormat == null)
228 Log.Error(PlayerLog.Tag, "Audio is not configured with the current source.");
229 throw new ArgumentException("Audio is not configured with the current source.");
232 _player.ValidatePlayerState(PlayerState.Paused, PlayerState.Playing, PlayerState.Ready);
234 NativePlayer.PushMediaStream(_player.Handle, packet.GetHandle()).
235 ThrowIfFailed("Failed to push the packet to the player");
238 private void SetMediaStreamInfo(StreamType streamType, MediaFormat mediaFormat)
240 if (mediaFormat == null)
242 Log.Error(PlayerLog.Tag, "invalid media format");
246 IntPtr ptr = IntPtr.Zero;
250 ptr = mediaFormat.AsNativeHandle();
251 NativePlayer.SetMediaStreamInfo(_player.Handle, (int)streamType, ptr).
252 ThrowIfFailed("Failed to set the media stream info");
256 MediaFormat.ReleaseNativeHandle(ptr);
260 internal override void OnAttached(Player player)
262 Debug.Assert(player != null);
266 Log.Error(PlayerLog.Tag, "The source is has already been assigned to another player.");
267 throw new InvalidOperationException("The source is has already been assigned to another player.");
270 AudioConfiguration?.OnPlayerSet(player);
271 VideoConfiguration?.OnPlayerSet(player);
275 SetMediaStreamInfo(StreamType.Audio, _audioMediaFormat);
276 SetMediaStreamInfo(StreamType.Video, _videoMediaFormat);
279 internal override void OnDetached(Player player)
281 base.OnDetached(player);
283 AudioConfiguration?.OnPlayerUnset(player);
284 VideoConfiguration?.OnPlayerUnset(player);
290 /// Gets the <see cref="Player"/> that this source is assigned to as a source or null if this source is not assigned.
292 /// <seealso cref="Player.SetSource(MediaSource)"/>
293 public Player Player => _player;