2 * Copyright (c) 2021 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.Remoting
26 /// Represents a media packet source.
28 /// <seealso cref="WebRTC.AddSource"/>
29 /// <seealso cref="WebRTC.AddSources"/>
30 /// <since_tizen> 9 </since_tizen>
31 public sealed class MediaPacketSource : MediaSource
33 private readonly MediaFormat _audioMediaFormat;
34 private readonly MediaFormat _videoMediaFormat;
35 private static List<MediaFormatAudioMimeType> _supportedAudioFormats;
36 private static List<MediaFormatVideoMimeType> _supportedVideoFormats;
39 /// Gets all supported audio types.
41 /// <since_tizen> 9 </since_tizen>
42 public static IEnumerable<MediaFormatAudioMimeType> SupportedAudioTypes
47 return _supportedAudioFormats.AsReadOnly();
52 /// Gets all supported video types.
54 /// <since_tizen> 9 </since_tizen>
55 public static IEnumerable<MediaFormatVideoMimeType> SupportedVideoTypes
60 return _supportedVideoFormats.AsReadOnly();
64 private static void GetSupportedTypes()
66 if (_supportedAudioFormats != null || _supportedVideoFormats != null)
71 // Currentely, supported formats are fixed in native fw but I'll keep this for future use.
72 _supportedAudioFormats = new List<MediaFormatAudioMimeType>()
74 MediaFormatAudioMimeType.Vorbis,
75 MediaFormatAudioMimeType.Opus,
76 MediaFormatAudioMimeType.Pcm
78 _supportedVideoFormats = new List<MediaFormatVideoMimeType>()
80 MediaFormatVideoMimeType.H264SP,
81 MediaFormatVideoMimeType.H264MP,
82 MediaFormatVideoMimeType.H264HP,
83 MediaFormatVideoMimeType.MJpeg,
84 MediaFormatVideoMimeType.Vp8,
85 MediaFormatVideoMimeType.Vp9,
86 MediaFormatVideoMimeType.I420,
87 MediaFormatVideoMimeType.NV12
91 private MediaPacketSourceConfiguration CreateAudioConfiguration(AudioMediaFormat format)
98 if (!SupportedAudioTypes.Contains<MediaFormatAudioMimeType>(format.MimeType))
100 throw new ArgumentException($"The audio format is not supported, Type : {format.MimeType}.");
103 return new MediaPacketSourceConfiguration(this);
106 private MediaPacketSourceConfiguration CreateVideoConfiguration(VideoMediaFormat format)
113 if (!SupportedVideoTypes.Contains(format.MimeType))
115 throw new ArgumentException($"The video format is not supported, Type : {format.MimeType}.");
117 return new MediaPacketSourceConfiguration(this);
121 /// Initializes a new instance of the MediaPacketSource class with the specified <see cref="AudioMediaFormat"/>.
123 /// <param name="audioMediaFormat">The <see cref="AudioMediaFormat"/> for this source.</param>
124 /// <exception cref="ArgumentNullException"><paramref name="audioMediaFormat"/> is null.</exception>
125 /// <exception cref="ArgumentException"><paramref name="audioMediaFormat"/> is not supported.</exception>
126 /// <seealso cref="SupportedAudioTypes"/>
127 /// <since_tizen> 9 </since_tizen>
128 public MediaPacketSource(AudioMediaFormat audioMediaFormat) : base(MediaType.Audio)
130 _audioMediaFormat = audioMediaFormat ?? throw new ArgumentNullException(nameof(audioMediaFormat));
131 AudioConfiguration = CreateAudioConfiguration(audioMediaFormat);
135 /// Initializes a new instance of the MediaPacketSource class with the specified <see cref="VideoMediaFormat"/>.
137 /// <param name="videoMediaFormat">The <see cref="VideoMediaFormat"/> for this source.</param>
138 /// <exception cref="ArgumentNullException"><paramref name="videoMediaFormat"/> is null.</exception>
139 /// <exception cref="ArgumentException"><paramref name="videoMediaFormat"/> is not supported.</exception>
140 /// <seealso cref="SupportedVideoTypes"/>
141 /// <since_tizen> 9 </since_tizen>
142 public MediaPacketSource(VideoMediaFormat videoMediaFormat) : base(MediaType.Video)
144 _videoMediaFormat = videoMediaFormat ?? throw new ArgumentNullException(nameof(videoMediaFormat));
145 VideoConfiguration = CreateVideoConfiguration(videoMediaFormat);
149 /// Gets the audio configuration, or null if no AudioMediaFormat is specified in the constructor.
151 /// <since_tizen> 9 </since_tizen>
152 public MediaPacketSourceConfiguration AudioConfiguration { get; }
155 /// Gets the video configuration, or null if no VideoMediaFormat is specified in the constructor.
157 /// <since_tizen> 9 </since_tizen>
158 public MediaPacketSourceConfiguration VideoConfiguration { get; }
161 /// Pushes elementary stream to decode audio or video.
164 /// This source must be set as a source to a WebRTC and the WebRTC must be in the
165 /// <see cref="WebRTCState.Negotiating"/> or <see cref="WebRTCState.Playing"/> state
167 /// <param name="packet">The <see cref="MediaPacket"/> to decode.</param>
168 /// <exception cref="InvalidOperationException">
169 /// This source is not set as a source to a WebRTC.<br/>
171 /// The WebRTC is not in the valid state.
173 /// <exception cref="ArgumentNullException"><paramref name="packet"/> is null.</exception>
174 /// <exception cref="ObjectDisposedException"><paramref name="packet"/> has been disposed.</exception>
175 /// <exception cref="ArgumentException">
176 /// <paramref name="packet"/> is neither video nor audio type.<br/>
178 /// The format of packet is not matched with the specified format in the constructor.
180 /// <seealso cref="WebRTC.AddSource"/>
181 /// <seealso cref="WebRTC.AddSources"/>
182 /// <seealso cref="MediaPacket"/>
183 /// <since_tizen> 9 </since_tizen>
184 public void Push(MediaPacket packet)
188 Log.Error(WebRTCLog.Tag, "The source is not set as a source to a WebRTC yet.");
189 throw new InvalidOperationException("The source is not set as a source to a WebRTC yet.");
194 Log.Error(WebRTCLog.Tag, "packet is null");
195 throw new ArgumentNullException(nameof(packet));
198 if (packet.IsDisposed)
200 Log.Error(WebRTCLog.Tag, "packet is disposed");
201 throw new ObjectDisposedException(nameof(packet));
204 if (packet.Format.Type == MediaFormatType.Text || packet.Format.Type == MediaFormatType.Container)
206 Log.Error(WebRTCLog.Tag, "The format of the packet is invalid : " + packet.Format.Type);
207 throw new ArgumentException($"The format of the packet is invalid : {packet.Format.Type}.");
210 if (!packet.Format.Equals(_audioMediaFormat) && !packet.Format.Equals(_videoMediaFormat))
212 Log.Error(WebRTCLog.Tag, "The format of the packet is invalid : Unmatched format.");
213 throw new ArgumentException("The format of the packet is invalid : Unmatched format.");
216 if (packet.Format.Type == MediaFormatType.Video && _videoMediaFormat == null)
218 Log.Error(WebRTCLog.Tag, "Video is not configured with the current source.");
219 throw new ArgumentException("Video is not configured with the current source.");
222 if (packet.Format.Type == MediaFormatType.Audio && _audioMediaFormat == null)
224 Log.Error(WebRTCLog.Tag, "Audio is not configured with the current source.");
225 throw new ArgumentException("Audio is not configured with the current source.");
228 NativeWebRTC.PushMediaPacket(WebRtc.Handle, SourceId.Value, packet.GetHandle()).
229 ThrowIfFailed("Failed to push the packet to the WebRTC");
232 private void SetMediaStreamInfo(MediaFormat mediaFormat)
234 if (mediaFormat == null)
239 IntPtr ptr = IntPtr.Zero;
243 ptr = mediaFormat.AsNativeHandle();
244 NativeWebRTC.SetMediaPacketSourceInfo(WebRtc.Handle, SourceId.Value, ptr).
245 ThrowIfFailed("Failed to set the media stream info");
249 MediaFormat.ReleaseNativeHandle(ptr);
253 internal override void OnAttached(WebRTC webRtc)
255 Debug.Assert(webRtc != null);
259 Log.Error(WebRTCLog.Tag, "The source is has already been assigned to another WebRTC.");
260 throw new InvalidOperationException("The source is has already been assigned to another WebRTC.");
263 NativeWebRTC.AddMediaSource(webRtc.Handle, MediaSourceType.MediaPacket, out uint sourceId).
264 ThrowIfFailed("Failed to add MediaPacketSource.");
269 AudioConfiguration?.OnWebRTCSet();
270 VideoConfiguration?.OnWebRTCSet();
272 SetMediaStreamInfo(_audioMediaFormat);
273 SetMediaStreamInfo(_videoMediaFormat);
276 internal override void OnDetached(WebRTC webRtc)
278 NativeWebRTC.RemoveMediaSource(webRtc.Handle, SourceId.Value).
279 ThrowIfFailed("Failed to remove MediaPacketSource.");
281 AudioConfiguration?.OnWebRTCUnset();
282 VideoConfiguration?.OnWebRTCUnset();