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
23 static internal class MetadataExtractorLog
25 internal const string Tag = "Tizen.Multimedia.MetadataExtractor";
29 /// Provides a means to get the metadata from a media file.
31 public class MetadataExtractor : IDisposable
33 private bool _disposed = false;
34 private IntPtr _handle = IntPtr.Zero;
35 private IntPtr _buffer = IntPtr.Zero;
37 private void Create(Func<MetadataExtractorError> initFunc)
39 MetadataExtractorRetValidator.ThrowIfError(
40 Interop.MetadataExtractor.Create(out _handle), "Failed to create metadata");
44 MetadataExtractorRetValidator.ThrowIfError(initFunc(), "Failed to init");
46 _metadata = new Lazy<Metadata>(() => new Metadata(Handle));
56 /// Initializes a new instance of the MetadataExtractor class with the specified path.
58 /// <since_tizen> 3 </since_tizen>
59 /// <param name="path">The path for the file to extract the metadata.</param>
60 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
61 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
62 public MetadataExtractor(string path)
66 throw new ArgumentNullException(nameof(path));
69 Create(() => Interop.MetadataExtractor.SetPath(_handle, path));
73 /// Initializes a new instance of the MetadataExtractor class with the specified buffer.
75 /// <since_tizen> 3 </since_tizen>
76 /// <param name="buffer">The buffer to extract the metadata.</param>
77 /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
78 /// <exception cref="ArgumentException">The length of <paramref name="buffer"/> is zero.</exception>
79 public MetadataExtractor(byte[] buffer)
83 throw new ArgumentNullException(nameof(buffer));
86 if (buffer.Length == 0)
88 throw new ArgumentException("buffer length is zero.", nameof(buffer));
91 _buffer = Marshal.AllocHGlobal(buffer.Length);
92 Marshal.Copy(buffer, 0, _buffer, buffer.Length);
96 Create(() => Interop.MetadataExtractor.SetBuffer(_handle, _buffer, buffer.Length));
100 Marshal.FreeHGlobal(_buffer);
105 private IntPtr Handle
111 throw new ObjectDisposedException(nameof(MetadataExtractor));
118 private Lazy<Metadata> _metadata;
121 /// Retrieves the <see cref="Metadata"/>.
123 /// <since_tizen> 3 </since_tizen>
124 /// <returns>The <see cref="Metadata"/> for the given source.</returns>
125 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
126 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
127 public Metadata GetMetadata()
131 throw new ObjectDisposedException(nameof(MetadataExtractor));
134 return _metadata.Value;
138 /// Gets the artwork image in the source.
140 /// <since_tizen> 3 </since_tizen>
141 /// <returns>The <see cref="Artwork"/> if it exists, otherwise null.</returns>
142 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
143 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
144 public Artwork GetArtwork()
146 IntPtr data = IntPtr.Zero;
147 IntPtr mimeType = IntPtr.Zero;
153 var ret = Interop.MetadataExtractor.GetArtwork(Handle, out data, out size, out mimeType);
154 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
158 var buf = new byte[size];
159 Marshal.Copy(data, buf, 0, size);
161 return new Artwork(buf, Marshal.PtrToStringAnsi(mimeType));
168 Interop.Libc.Free(data);
169 Interop.Libc.Free(mimeType);
174 /// Gets the sync lyrics of the source.
176 /// <since_tizen> 3 </since_tizen>
177 /// <param name="index">The index of lyrics to retrieve.</param>
178 /// <returns>The <see cref="SyncLyrics"/> object if <paramref name="index"/> is valid, otherwise null.</returns>
179 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
180 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
181 public SyncLyrics GetSyncLyrics(int index)
183 IntPtr lyrics = IntPtr.Zero;
189 var ret = Interop.MetadataExtractor.GetSynclyrics(Handle, index, out timestamp, out lyrics);
190 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get sync lyrics");
192 if (lyrics == IntPtr.Zero)
197 return new SyncLyrics(Marshal.PtrToStringAnsi(lyrics), timestamp);
201 Interop.Libc.Free(lyrics);
206 /// Gets the frame of a video media.
208 /// <since_tizen> 3 </since_tizen>
209 /// <returns>The raw thumbnail data in RGB888 if it exists, otherwise null.</returns>
210 /// <exception cref="InvalidOperationException">An internal process error occurs.</exception>
211 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
212 public byte[] GetVideoThumbnail()
214 IntPtr data = IntPtr.Zero;
220 var ret = Interop.MetadataExtractor.GetFrame(Handle, out data, out size);
221 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
228 var buf = new byte[size];
229 Marshal.Copy(data, buf, 0, size);
235 Interop.Libc.Free(data);
240 /// Gets the frame of a video media.
242 /// <since_tizen> 3 </since_tizen>
243 /// <param name="timeStamp">The timestamp in milliseconds.</param>
244 /// <param name="accurate">true to get an accurate frame for the given timestamp,
245 /// otherwise false to get the nearest i-frame of the video rapidly.</param>
246 /// <returns>The raw frame data in RGB888 if a frame at specified time exists, otherwise null.</returns>
247 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
248 /// <exception cref="ObjectDisposedException">The <see cref="MetadataExtractor"/> has been already disposed of.</exception>
249 public byte[] GetFrameAt(uint timeStamp, bool accurate)
251 IntPtr data = IntPtr.Zero;
257 var ret = Interop.MetadataExtractor.GetFrameAtTime(Handle, timeStamp, accurate, out data, out size);
258 MetadataExtractorRetValidator.ThrowIfError(ret, "Failed to get value");
265 var buf = new byte[size];
266 Marshal.Copy(data, buf, 0, size);
272 Interop.Libc.Free(data);
281 protected virtual void Dispose(bool disposing)
290 private void Release()
292 if (_buffer != IntPtr.Zero)
294 Marshal.FreeHGlobal(_buffer);
297 if (_handle != IntPtr.Zero)
299 var ret = Interop.MetadataExtractor.Destroy(_handle);
300 Log.Error(MetadataExtractorLog.Tag, $"DestroyHandle failed : {ret}.");
302 _handle = IntPtr.Zero;
307 /// Releases all resources used by the <see cref="MetadataExtractor"/> object.
309 public void Dispose()
312 GC.SuppressFinalize(this);