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 public class MetadataExtractor : IDisposable
28 private bool _disposed = false;
29 private IntPtr _handle = IntPtr.Zero;
30 private IntPtr _buffer = IntPtr.Zero;
32 private void Create(Func<MetadataExtractorError> initFunc)
34 MetadataExtractorRetValidator.ThrowIfError(
35 Interop.MetadataExtractor.Create(out _handle), "Failed to create metadata");
39 MetadataExtractorRetValidator.ThrowIfError(initFunc(), "Failed to init");
41 _metadata = new Lazy<Metadata>(() => new Metadata(this));
51 /// Initializes a new instance of the MetadataExtractor class with the specified path.
53 /// <since_tizen> 3 </since_tizen>
54 /// <param name="path">The path for the file to extract the metadata.</param>
55 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
56 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
57 public MetadataExtractor(string path)
61 throw new ArgumentNullException(nameof(path));
64 Create(() => Interop.MetadataExtractor.SetPath(_handle, path));
68 /// Initializes a new instance of the MetadataExtractor class with the specified buffer.
70 /// <since_tizen> 3 </since_tizen>
71 /// <param name="buffer">The buffer to extract the metadata.</param>
72 /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
73 /// <exception cref="ArgumentException">The length of <paramref name="buffer"/> is zero.</exception>
74 public MetadataExtractor(byte[] buffer)
78 throw new ArgumentNullException(nameof(buffer));
81 if (buffer.Length == 0)
83 throw new ArgumentException("buffer length is zero.", nameof(buffer));
86 _buffer = Marshal.AllocHGlobal(buffer.Length);
87 Marshal.Copy(buffer, 0, _buffer, buffer.Length);
91 Create(() => Interop.MetadataExtractor.SetBuffer(_handle, _buffer, buffer.Length));
95 Marshal.FreeHGlobal(_buffer);
100 internal IntPtr Handle
106 throw new ObjectDisposedException(nameof(MetadataExtractor));
113 private Lazy<Metadata> _metadata;
116 /// Retrieves the <see cref="Metadata"/>.
118 /// <since_tizen> 3 </since_tizen>
119 /// <returns>The <see cref="Metadata"/> for the given source.</returns>
120 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
121 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
122 public Metadata GetMetadata()
126 throw new ObjectDisposedException(nameof(MetadataExtractor));
129 return _metadata.Value;
133 /// Gets the artwork image in the source.
135 /// <since_tizen> 3 </since_tizen>
136 /// <returns>The <see cref="Artwork"/> if it exists, otherwise null.</returns>
137 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
138 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
139 public Artwork GetArtwork()
141 IntPtr data = IntPtr.Zero;
142 IntPtr mimeType = IntPtr.Zero;
148 var ret = Interop.MetadataExtractor.GetArtwork(Handle, out data, out size, out mimeType);
149 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
153 var buf = new byte[size];
154 Marshal.Copy(data, buf, 0, size);
156 return new Artwork(buf, Marshal.PtrToStringAnsi(mimeType));
163 Interop.Libc.Free(data);
164 Interop.Libc.Free(mimeType);
169 /// Gets the sync lyrics of the source.
171 /// <since_tizen> 3 </since_tizen>
172 /// <param name="index">The index of lyrics to retrieve.</param>
173 /// <returns>The <see cref="SyncLyrics"/> object if <paramref name="index"/> is valid, otherwise null.</returns>
174 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
175 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
176 public SyncLyrics GetSyncLyrics(int index)
178 IntPtr lyrics = IntPtr.Zero;
184 var ret = Interop.MetadataExtractor.GetSynclyrics(Handle, index, out timestamp, out lyrics);
185 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get sync lyrics");
187 if (lyrics == IntPtr.Zero)
192 return new SyncLyrics(Marshal.PtrToStringAnsi(lyrics), timestamp);
196 Interop.Libc.Free(lyrics);
201 /// Gets the frame of a video media.
203 /// <since_tizen> 3 </since_tizen>
204 /// <returns>The raw thumbnail data in RGB888 if it exists, otherwise null.</returns>
205 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
206 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
207 public byte[] GetVideoThumbnail()
209 IntPtr data = IntPtr.Zero;
215 var ret = Interop.MetadataExtractor.GetFrame(Handle, out data, out size);
216 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
223 var buf = new byte[size];
224 Marshal.Copy(data, buf, 0, size);
230 Interop.Libc.Free(data);
235 /// Gets the frame of a video media.
237 /// <since_tizen> 3 </since_tizen>
238 /// <param name="timeStamp">The timestamp in milliseconds.</param>
239 /// <param name="accurate">true to get an accurate frame for the given timestamp,
240 /// otherwise false to get the nearest i-frame of the video rapidly.</param>
241 /// <returns>The raw frame data in RGB888 if a frame at specified time exists, otherwise null.</returns>
242 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
243 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
244 public byte[] GetFrameAt(uint timeStamp, bool accurate)
246 IntPtr data = IntPtr.Zero;
252 var ret = Interop.MetadataExtractor.GetFrameAtTime(Handle, timeStamp, accurate, out data, out size);
253 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
260 var buf = new byte[size];
261 Marshal.Copy(data, buf, 0, size);
267 Interop.Libc.Free(data);
277 /// Releases the resources used by the <see cref="MetadataExtractor"/> object.
279 /// <param name="disposing">
280 /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
282 protected virtual void Dispose(bool disposing)
291 private void Release()
293 if (_buffer != IntPtr.Zero)
295 Marshal.FreeHGlobal(_buffer);
296 _buffer = IntPtr.Zero;
299 if (_handle != IntPtr.Zero)
301 var ret = Interop.MetadataExtractor.Destroy(_handle);
302 if (ret != MetadataExtractorError.None)
304 Log.Error(typeof(MetadataExtractor).FullName, $"DestroyHandle failed : {ret}.");
307 _handle = IntPtr.Zero;
312 /// Releases all resources used by the <see cref="MetadataExtractor"/> object.
314 public void Dispose()
317 GC.SuppressFinalize(this);