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.
18 using System.Runtime.InteropServices;
20 namespace Tizen.Multimedia
22 static internal class MetadataExtractorLog
24 internal const string Tag = "Tizen.Multimedia.MetadataExtractor";
28 /// Provides a set of functions to get the metadata from a media file.
30 public class MetadataExtractor : IDisposable
32 private bool _disposed = false;
33 private IntPtr _handle = IntPtr.Zero;
34 private IntPtr _buffer = IntPtr.Zero;
36 private void Create(Func<MetadataExtractorError> initFunc)
38 MetadataExtractorRetValidator.ThrowIfError(
39 Interop.MetadataExtractor.Create(out _handle), "Failed to create metadata");
43 MetadataExtractorRetValidator.ThrowIfError(initFunc(), "Failed to init");
45 _metadata = new Lazy<Metadata>(() => new Metadata(Handle));
55 /// Initializes a new instance of the MetadataExtractor class with the specified path.
57 /// <since_tizen> 3 </since_tizen>
58 /// <param name="path">The path for the file to extract metadata.</param>
59 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
60 /// <exception cref="FileNotFoundException"><paramref name="path"/> is not exist.</exception>
61 public MetadataExtractor(string path)
65 throw new ArgumentNullException(nameof(path));
68 Create(() => Interop.MetadataExtractor.SetPath(_handle, path));
72 /// Initializes a new instance of the MetadataExtractor class with the specified buffer.
74 /// <since_tizen> 3 </since_tizen>
75 /// <param name="buffer">The buffer to extract metadata.</param>
76 /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
77 /// <exception cref="ArgumentException">The length of <paramref name="buffer"/> is zero.</exception>
78 public MetadataExtractor(byte[] buffer)
82 throw new ArgumentNullException(nameof(buffer));
85 if (buffer.Length == 0)
87 throw new ArgumentException("buffer length is zero.", nameof(buffer));
90 _buffer = Marshal.AllocHGlobal(buffer.Length);
91 Marshal.Copy(buffer, 0, _buffer, buffer.Length);
95 Create(() => Interop.MetadataExtractor.SetBuffer(_handle, _buffer, buffer.Length));
99 Marshal.FreeHGlobal(_buffer);
104 private IntPtr Handle
110 throw new ObjectDisposedException(nameof(MetadataExtractor));
117 private Lazy<Metadata> _metadata;
120 /// Retrieves the <see cref="Metadata"/>.
122 /// <since_tizen> 3 </since_tizen>
123 /// <returns>A <see cref="Metadata"/> for the given source.</returns>
124 /// <exception cref="InvalidOperationException">Internal process error is occurred.</exception>
125 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
126 public Metadata GetMetadata()
130 throw new ObjectDisposedException(nameof(MetadataExtractor));
133 return _metadata.Value;
137 /// Gets the artwork image in the source.
139 /// <since_tizen> 3 </since_tizen>
140 /// <returns>A <see cref="Artwork"/> if it exists, otherwise null.</returns>
141 /// <exception cref="InvalidOperationException">Internal process error is occurred.</exception>
142 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
143 public Artwork GetArtwork()
145 IntPtr data = IntPtr.Zero;
146 IntPtr mimeType = IntPtr.Zero;
152 var ret = Interop.MetadataExtractor.GetArtwork(Handle, out data, out size, out mimeType);
153 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
157 var buf = new byte[size];
158 Marshal.Copy(data, buf, 0, size);
160 return new Artwork(buf, Marshal.PtrToStringAnsi(mimeType));
167 Interop.Libc.Free(data);
168 Interop.Libc.Free(mimeType);
173 /// Gets the sync lyrics of the source.
175 /// <since_tizen> 3 </since_tizen>
176 /// <param name="index">The index of lyrics to retrieve.</param>
177 /// <returns>A <see cref="SyncLyrics"/> object if <paramref name="index"/> is valid, otherwise null.</returns>
178 /// <exception cref="InvalidOperationException">Internal process error is occurred.</exception>
179 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
180 public SyncLyrics GetSyncLyrics(int index)
182 IntPtr lyrics = IntPtr.Zero;
188 var ret = Interop.MetadataExtractor.GetSynclyrics(Handle, index, out timestamp, out lyrics);
189 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get sync lyrics");
191 if (lyrics == IntPtr.Zero)
196 return new SyncLyrics(Marshal.PtrToStringAnsi(lyrics), timestamp);
200 Interop.Libc.Free(lyrics);
205 /// Gets the frame of a video media.
207 /// <since_tizen> 3 </since_tizen>
208 /// <returns>The raw thumbnail data in RGB888 if it exists, otherwise null.</returns>
209 /// <exception cref="InvalidOperationException">Internal process error is occurred.</exception>
210 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
211 public byte[] GetVideoThumbnail()
213 IntPtr data = IntPtr.Zero;
219 var ret = Interop.MetadataExtractor.GetFrame(Handle, out data, out size);
220 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
227 var buf = new byte[size];
228 Marshal.Copy(data, buf, 0, size);
234 Interop.Libc.Free(data);
239 /// Gets the frame of a video media.
241 /// <since_tizen> 3 </since_tizen>
242 /// <param name="timeStamp">The timestamp in milliseconds.</param>
243 /// <param name="accurate">true to get an accurate frame for the given timestamp,
244 /// otherwise false to get the nearest i-frame of the video rapidly.</param>
245 /// <returns>The raw frame data in RGB888 if a frame at specified time exists, otherwise null.</returns>
246 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
247 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
248 public byte[] GetFrameAt(uint timeStamp, bool accurate)
250 IntPtr data = IntPtr.Zero;
256 var ret = Interop.MetadataExtractor.GetFrameAtTime(Handle, timeStamp, accurate, out data, out size);
257 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
264 var buf = new byte[size];
265 Marshal.Copy(data, buf, 0, size);
271 Interop.Libc.Free(data);
276 /// Metadata Extractor destructor
278 /// <since_tizen> 3 </since_tizen>
284 protected virtual void Dispose(bool disposing)
293 private void Release()
295 if (_buffer != IntPtr.Zero)
297 Marshal.FreeHGlobal(_buffer);
300 if (_handle != IntPtr.Zero)
302 var ret = Interop.MetadataExtractor.Destroy(_handle);
303 Log.Error(MetadataExtractorLog.Tag, $"DestroyHandle failed : {ret}.");
305 _handle = IntPtr.Zero;
310 /// Releases all resources used by the <see cref="MetadataExtractor"/> object.
312 public void Dispose()
315 GC.SuppressFinalize(this);