[Multimedia] Fix ASAN crash issue (#5699)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.MediaPlayer / Player / StreamInfo.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 using System;
17 using System.Runtime.InteropServices;
18 using static Interop;
19
20 namespace Tizen.Multimedia
21 {
22     /// <summary>
23     /// Represents properties for the audio stream.
24     /// </summary>
25     /// <since_tizen> 3 </since_tizen>
26     public struct AudioStreamProperties
27     {
28         /// <summary>
29         /// Initializes a new instance of the AudioStreamProperties struct with the specified sample rate, channels, and bit rate.
30         /// </summary>
31         /// <param name="sampleRate">The sample rate of the stream.</param>
32         /// <param name="channels">The number of channels of the stream.</param>
33         /// <param name="bitRate">The bit rate of the stream.</param>
34         /// <since_tizen> 3 </since_tizen>
35         public AudioStreamProperties(int sampleRate, int channels, int bitRate)
36         {
37             SampleRate = sampleRate;
38             Channels = channels;
39             BitRate = bitRate;
40
41             Log.Debug(PlayerLog.Tag, $"sampleRate={sampleRate}, channels={channels}, bitRate={bitRate}");
42         }
43
44         /// <summary>
45         /// Gets or sets the sample rate.
46         /// </summary>
47         /// <value>The audio sample rate(Hz).</value>
48         /// <since_tizen> 3 </since_tizen>
49         public int SampleRate
50         {
51             get;
52             set;
53         }
54
55         /// <summary>
56         /// Gets or sets the channels.
57         /// </summary>
58         /// <since_tizen> 3 </since_tizen>
59         public int Channels
60         {
61             get;
62             set;
63         }
64
65         /// <summary>
66         /// Gets or sets the bit rate.
67         /// </summary>
68         /// <value>The audio bit rate(Hz).</value>
69         /// <since_tizen> 3 </since_tizen>
70         public int BitRate
71         {
72             get;
73             set;
74         }
75
76         /// <summary>
77         /// Returns a string that represents the current object.
78         /// </summary>
79         /// <returns>A string that represents the current object.</returns>
80         /// <since_tizen> 3 </since_tizen>
81         public override string ToString() =>
82             $"SampleRate={ SampleRate.ToString() }, Channels={ Channels.ToString() }, BitRate={ BitRate.ToString() }";
83     }
84
85     /// <summary>
86     /// Represents properties for the video stream.
87     /// </summary>
88     /// <since_tizen> 3 </since_tizen>
89     public struct VideoStreamProperties
90     {
91         /// <summary>
92         /// Initializes a new instance of the VideoStreamProperties struct with the specified fps, bit rate, and size.
93         /// </summary>
94         /// <param name="fps">The fps of the stream.</param>
95         /// <param name="bitRate">The bit rate of the stream.</param>
96         /// <param name="size">The size of the stream.</param>
97         /// <since_tizen> 3 </since_tizen>
98         public VideoStreamProperties(int fps, int bitRate, Size size)
99         {
100             Fps = fps;
101             BitRate = bitRate;
102             Size = size;
103             Log.Debug(PlayerLog.Tag, $"fps={fps}, bitrate={bitRate}, size=({size})");
104         }
105         /// <summary>
106         /// Initializes a new instance of the VideoStreamProperties struct with the specified fps, bit rate, width, and height.
107         /// </summary>
108         /// <param name="fps">The fps of the stream.</param>
109         /// <param name="bitRate">The bit rate of the stream.</param>
110         /// <param name="width">The width of the stream.</param>
111         /// <param name="height">The height of the stream.</param>
112         /// <since_tizen> 3 </since_tizen>
113         public VideoStreamProperties(int fps, int bitRate, int width, int height)
114             : this(fps, bitRate, new Size(width, height))
115         {
116         }
117
118         /// <summary>
119         /// Gets or sets the fps.
120         /// </summary>
121         /// <since_tizen> 3 </since_tizen>
122         public int Fps
123         {
124             get;
125             set;
126         }
127         /// <summary>
128         /// Gets or sets the bit rate.
129         /// </summary>
130         /// <since_tizen> 3 </since_tizen>
131         public int BitRate
132         {
133             get;
134             set;
135         }
136
137         /// <summary>
138         /// Gets or sets the size.
139         /// </summary>
140         /// <since_tizen> 3 </since_tizen>
141         public Size Size
142         {
143             get;
144             set;
145         }
146
147         /// <summary>
148         /// Returns a string that represents the current object.
149         /// </summary>
150         /// <returns>A string that represents the current object.</returns>
151         /// <since_tizen> 3 </since_tizen>
152         public override string ToString()
153         {
154             return $"Fps={ Fps.ToString() }, BitRate={ BitRate.ToString() }, Size=[{ Size.ToString() }]";
155         }
156     }
157
158     /// <summary>
159     /// Provides a means to retrieve stream information.
160     /// </summary>
161     /// <since_tizen> 3 </since_tizen>
162     public class StreamInfo
163     {
164         internal StreamInfo(Player owner)
165         {
166             Player = owner;
167         }
168
169         /// <summary>
170         /// Retrieves the album art of the stream, or null if there is no album art data.
171         /// </summary>
172         /// <returns>Raw byte array if album art exists; otherwise null.</returns>
173         /// <remarks>
174         /// The <see cref="Multimedia.Player"/> that owns this instance must be in the <see cref="PlayerState.Ready"/>,
175         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
176         /// </remarks>
177         /// <exception cref="ObjectDisposedException">
178         /// The <see cref="Multimedia.Player"/> that this instance belongs to has been disposed of.
179         /// </exception>
180         /// <exception cref="InvalidOperationException">
181         /// The <see cref="Multimedia.Player"/> that this instance belongs to is not in the valid state.
182         /// </exception>
183         /// <since_tizen> 3 </since_tizen>
184         public byte[] GetAlbumArt()
185         {
186             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
187
188             NativePlayer.GetAlbumArt(Player.Handle, out var art, out var size).
189                 ThrowIfFailed(Player, "Failed to get the album art");
190
191             if (art == IntPtr.Zero || size == 0)
192             {
193                 return null;
194             }
195
196             byte[] albumArt = new byte[size];
197             Marshal.Copy(art, albumArt, 0, size);
198             return albumArt;
199         }
200
201         private string GetCodecInfo(bool audioInfo)
202         {
203             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
204
205             IntPtr audioPtr = IntPtr.Zero;
206             IntPtr videoPtr = IntPtr.Zero;
207             try
208             {
209                 NativePlayer.GetCodecInfo(Player.Handle, out audioPtr, out videoPtr).
210                     ThrowIfFailed(Player, "Failed to get codec info");
211
212                 if (audioInfo)
213                 {
214                     Log.Debug(PlayerLog.Tag, "it is audio case");
215                     return Marshal.PtrToStringAnsi(audioPtr);
216                 }
217                 else
218                 {
219                     Log.Debug(PlayerLog.Tag, "it is video case");
220                     return Marshal.PtrToStringAnsi(videoPtr);
221                 }
222             }
223             finally
224             {
225                 Marshal.FreeHGlobal(audioPtr);
226                 Marshal.FreeHGlobal(videoPtr);
227             }
228         }
229
230         /// <summary>
231         /// Retrieves the codec name of the audio or null if there is no audio.
232         /// </summary>
233         /// <returns>A string that represents the codec name.</returns>
234         /// <since_tizen> 3 </since_tizen>
235         public string GetAudioCodec()
236         {
237             return GetCodecInfo(true);
238         }
239
240         /// <summary>
241         /// Retrieves the codec name of the video or null if there is no video.
242         /// </summary>
243         /// <returns>A string that represents the codec name.</returns>
244         /// <since_tizen> 3 </since_tizen>
245         public string GetVideoCodec()
246         {
247             return GetCodecInfo(false);
248         }
249
250         /// <summary>
251         /// Gets the duration.
252         /// </summary>
253         /// <returns>The duration of the stream.</returns>
254         /// <remarks>
255         /// The <see cref="Multimedia.Player"/> that owns this instance must be in the <see cref="PlayerState.Ready"/>,
256         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
257         /// </remarks>
258         /// <exception cref="ObjectDisposedException">
259         /// The <see cref="Multimedia.Player"/> that this instance belongs to has been disposed of.
260         /// </exception>
261         /// <exception cref="InvalidOperationException">
262         /// The <see cref="Multimedia.Player"/> that this instance belongs to is not in the valid state.
263         /// </exception>\
264         /// <seealso cref="GetDurationNanoseconds"/>
265         /// <since_tizen> 3 </since_tizen>
266         public int GetDuration()
267         {
268             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
269
270             NativePlayer.GetDuration(Player.Handle, out var duration).
271                 ThrowIfFailed(Player, "Failed to get the duration");
272
273             Log.Info(PlayerLog.Tag, "get duration : " + duration);
274             return duration;
275         }
276
277         /// <summary>
278         /// Gets the duration in nanoseconds.
279         /// </summary>
280         /// <returns>The duration of the stream.</returns>
281         /// <remarks>
282         /// The <see cref="Multimedia.Player"/> that owns this instance must be in the <see cref="PlayerState.Ready"/>,
283         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
284         /// </remarks>
285         /// <exception cref="ObjectDisposedException">
286         /// The <see cref="Multimedia.Player"/> that this instance belongs to has been disposed of.
287         /// </exception>
288         /// <exception cref="InvalidOperationException">
289         /// The <see cref="Multimedia.Player"/> that this instance belongs to is not in the valid state.
290         /// </exception>
291         /// <seealso cref="GetDuration"/>
292         /// <since_tizen> 5 </since_tizen>
293         public long GetDurationNanoseconds()
294         {
295             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
296
297             NativePlayer.GetDurationNanoseconds(Player.Handle, out var duration).
298                 ThrowIfFailed(Player, "Failed to get the duration in nanoseconds");
299
300             Log.Info(PlayerLog.Tag, "get duration(nsec) : " + duration);
301             return duration;
302         }
303
304         /// <summary>
305         /// Gets the properties of the audio.
306         /// </summary>
307         /// <returns>A <see cref="AudioStreamProperties"/> that contains the audio stream information.</returns>
308         /// <remarks>
309         /// The <see cref="Multimedia.Player"/> that owns this instance must be in the <see cref="PlayerState.Ready"/>,
310         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
311         /// </remarks>
312         /// <exception cref="ObjectDisposedException">
313         /// The <see cref="Multimedia.Player"/> that this instance belongs to has been disposed of.
314         /// </exception>
315         /// <exception cref="InvalidOperationException">
316         /// The <see cref="Multimedia.Player"/> that this instance belongs to is not in the valid state.
317         /// </exception>
318         /// <since_tizen> 3 </since_tizen>
319         public AudioStreamProperties GetAudioProperties()
320         {
321             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
322
323             NativePlayer.GetAudioStreamInfo(Player.Handle, out var sampleRate,
324                 out var channels, out var bitRate).
325                 ThrowIfFailed(Player, "Failed to get audio stream info");
326
327             return new AudioStreamProperties(sampleRate, channels, bitRate);
328         }
329
330         /// <summary>
331         /// Gets the properties of the video.
332         /// </summary>
333         /// <returns>A <see cref="VideoStreamProperties"/> that contains the video stream information.</returns>
334         /// <remarks>
335         /// The <see cref="Multimedia.Player"/> that owns this instance must be in the <see cref="PlayerState.Ready"/>,
336         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
337         /// </remarks>
338         /// <exception cref="ObjectDisposedException">
339         /// The <see cref="Multimedia.Player"/> that this instance belongs to has been disposed of.
340         /// </exception>
341         /// <exception cref="InvalidOperationException">
342         /// The <see cref="Multimedia.Player"/> that this instance belongs to is not in the valid state.
343         /// </exception>
344         /// <since_tizen> 3 </since_tizen>
345         public VideoStreamProperties GetVideoProperties()
346         {
347             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
348
349             NativePlayer.GetVideoStreamInfo(Player.Handle, out var fps, out var bitRate).
350                 ThrowIfFailed(Player, "Failed to get the video stream info");
351
352             return new VideoStreamProperties(fps, bitRate, GetVideoSize());
353         }
354
355         private Size GetVideoSize()
356         {
357             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
358
359             NativePlayer.GetVideoSize(Player.Handle, out var width, out var height).
360                 ThrowIfFailed(Player, "Failed to get the video size");
361
362             return new Size(width, height);
363         }
364
365         /// <summary>
366         /// Gets the metadata with the specified key.
367         /// </summary>
368         /// <returns>A string that represents the value of the specified key.</returns>
369         /// <param name="key">The key to query.</param>
370         /// <remarks>
371         /// The <see cref="Multimedia.Player"/> that owns this instance must be in the <see cref="PlayerState.Ready"/>,
372         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.</remarks>
373         /// <exception cref="ObjectDisposedException">
374         /// The <see cref="Multimedia.Player"/> that this instance belongs to has been disposed of.
375         /// </exception>
376         /// <exception cref="InvalidOperationException">
377         /// The <see cref="Multimedia.Player"/> that this instance belongs to is not in the valid state.
378         /// </exception>
379         /// <since_tizen> 3 </since_tizen>
380         public string GetMetadata(StreamMetadataKey key)
381         {
382             Player.ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
383
384             ValidationUtil.ValidateEnum(typeof(StreamMetadataKey), key, nameof(key));
385
386             IntPtr ptr = IntPtr.Zero;
387
388             try
389             {
390                 NativePlayer.GetContentInfo(Player.Handle, key, out ptr).
391                     ThrowIfFailed(Player, $"Failed to get the meta data with the key '{ key }'");
392
393                 return Marshal.PtrToStringAnsi(ptr);
394             }
395             finally
396             {
397                 Marshal.FreeHGlobal(ptr);
398             }
399         }
400
401         /// <summary>
402         /// Gets the <see cref="Multimedia.Player"/> that owns this instance.
403         /// </summary>
404         /// <since_tizen> 3 </since_tizen>
405         public Player Player { get; }
406     }
407 }