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.
19 using System.Runtime.InteropServices;
21 namespace Tizen.Multimedia
24 /// Provides a means to get the metadata from a media file.
26 /// <since_tizen> 3 </since_tizen>
27 public class MetadataExtractor : IDisposable
29 private bool _disposed = false;
30 private IntPtr _handle = IntPtr.Zero;
31 private IntPtr _buffer = IntPtr.Zero;
33 private void Create(Func<MetadataExtractorError> initFunc)
35 MetadataExtractorRetValidator.ThrowIfError(
36 Interop.MetadataExtractor.Create(out _handle), "Failed to create metadata");
40 MetadataExtractorRetValidator.ThrowIfError(initFunc(), "Failed to init");
42 _metadata = new Lazy<Metadata>(() => new Metadata(this));
52 /// Initializes a new instance of the MetadataExtractor class with the specified path.
54 /// <since_tizen> 3 </since_tizen>
55 /// <param name="path">The path for the file to extract the metadata.</param>
56 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
57 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
58 public MetadataExtractor(string path)
62 throw new ArgumentNullException(nameof(path));
65 Create(() => Interop.MetadataExtractor.SetPath(_handle, path));
69 /// Initializes a new instance of the MetadataExtractor class with the specified buffer.
71 /// <since_tizen> 3 </since_tizen>
72 /// <param name="buffer">The buffer to extract the metadata.</param>
73 /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
74 /// <exception cref="ArgumentException">The length of <paramref name="buffer"/> is zero.</exception>
75 public MetadataExtractor(byte[] buffer)
79 throw new ArgumentNullException(nameof(buffer));
82 if (buffer.Length == 0)
84 throw new ArgumentException("buffer length is zero.", nameof(buffer));
87 _buffer = Marshal.AllocHGlobal(buffer.Length);
88 Marshal.Copy(buffer, 0, _buffer, buffer.Length);
92 Create(() => Interop.MetadataExtractor.SetBuffer(_handle, _buffer, buffer.Length));
96 Marshal.FreeHGlobal(_buffer);
101 internal IntPtr Handle
107 throw new ObjectDisposedException(nameof(MetadataExtractor));
114 private Lazy<Metadata> _metadata;
117 /// Retrieves the <see cref="Metadata"/>.
119 /// <since_tizen> 3 </since_tizen>
120 /// <returns>The <see cref="Metadata"/> for the given source.</returns>
121 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
122 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
123 public Metadata GetMetadata()
127 throw new ObjectDisposedException(nameof(MetadataExtractor));
130 return _metadata.Value;
134 /// Gets the artwork image in the source.
136 /// <since_tizen> 3 </since_tizen>
137 /// <returns>The <see cref="Artwork"/> if it exists, otherwise null.</returns>
138 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
139 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
140 public Artwork GetArtwork()
142 IntPtr data = IntPtr.Zero;
143 IntPtr mimeType = IntPtr.Zero;
149 var ret = Interop.MetadataExtractor.GetArtwork(Handle, out data, out size, out mimeType);
150 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
154 var buf = new byte[size];
155 Marshal.Copy(data, buf, 0, size);
157 return new Artwork(buf, Marshal.PtrToStringAnsi(mimeType));
164 Interop.Libc.Free(data);
165 Interop.Libc.Free(mimeType);
170 /// Gets the sync lyrics of the source.
172 /// <since_tizen> 3 </since_tizen>
173 /// <param name="index">The index of lyrics to retrieve.</param>
174 /// <returns>The <see cref="SyncLyrics"/> object if <paramref name="index"/> is valid, otherwise null.</returns>
175 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
176 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
177 public SyncLyrics GetSyncLyrics(int index)
179 IntPtr lyrics = IntPtr.Zero;
185 var ret = Interop.MetadataExtractor.GetSynclyrics(Handle, index, out timestamp, out lyrics);
186 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get sync lyrics");
188 if (lyrics == IntPtr.Zero)
193 return new SyncLyrics(Marshal.PtrToStringAnsi(lyrics), timestamp);
197 Interop.Libc.Free(lyrics);
202 /// Gets the frame of a video media.
204 /// <since_tizen> 3 </since_tizen>
205 /// <returns>The raw thumbnail data in RGB888 if it exists, otherwise null.</returns>
206 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
207 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
208 public byte[] GetVideoThumbnail()
210 IntPtr data = IntPtr.Zero;
216 var ret = Interop.MetadataExtractor.GetFrame(Handle, out data, out size);
217 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
224 var buf = new byte[size];
225 Marshal.Copy(data, buf, 0, size);
231 Interop.Libc.Free(data);
236 /// Gets the frame of a video media.
238 /// <since_tizen> 3 </since_tizen>
239 /// <param name="timeStamp">The timestamp in milliseconds.</param>
240 /// <param name="accurate">true to get an accurate frame for the given timestamp,
241 /// otherwise false to get the nearest i-frame of the video rapidly.</param>
242 /// <returns>The raw frame data in RGB888 if a frame at specified time exists, otherwise null.</returns>
243 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
244 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
245 public byte[] GetFrameAt(uint timeStamp, bool accurate)
247 IntPtr data = IntPtr.Zero;
253 var ret = Interop.MetadataExtractor.GetFrameAtTime(Handle, timeStamp, accurate, out data, out size);
254 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
261 var buf = new byte[size];
262 Marshal.Copy(data, buf, 0, size);
268 Interop.Libc.Free(data);
273 /// Finalizes an instance of the MetadataExtractor class.
281 /// Releases the resources used by the <see cref="MetadataExtractor"/> object.
283 /// <param name="disposing">
284 /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
286 /// <since_tizen> 3 </since_tizen>
287 protected virtual void Dispose(bool disposing)
296 private void Release()
298 if (_buffer != IntPtr.Zero)
300 Marshal.FreeHGlobal(_buffer);
301 _buffer = IntPtr.Zero;
304 if (_handle != IntPtr.Zero)
306 var ret = Interop.MetadataExtractor.Destroy(_handle);
307 if (ret != MetadataExtractorError.None)
309 Log.Error(typeof(MetadataExtractor).FullName, $"DestroyHandle failed : {ret}.");
312 _handle = IntPtr.Zero;
317 /// Releases all resources used by the <see cref="MetadataExtractor"/> object.
319 /// <since_tizen> 3 </since_tizen>
320 public void Dispose()
323 GC.SuppressFinalize(this);