[MediaVision] Refactoring
authorTae-Young Chung <ty83.chung@samsung.com>
Tue, 21 Mar 2017 04:03:40 +0000 (13:03 +0900)
committerTae-Young Chung <ty83.chung@samsung.com>
Thu, 23 Mar 2017 12:01:03 +0000 (05:01 -0700)
Change-Id: Ic6b2077c111062accf203535257b45b50596dc1d
Signed-off-by: Tae-Young Chung <ty83.chung@samsung.com>
77 files changed:
packaging/csapi-multimedia.spec
src/Tizen.Multimedia/Common/IBufferOwner.cs [new file with mode: 0644]
src/Tizen.Multimedia/Common/IMediaBuffer.cs [new file with mode: 0644]
src/Tizen.Multimedia/Common/MultimediaLog.cs [new file with mode: 0644]
src/Tizen.Multimedia/Common/ObjectKeeper.cs [new file with mode: 0644]
src/Tizen.Multimedia/Common/Point.cs
src/Tizen.Multimedia/Common/Range.cs
src/Tizen.Multimedia/Common/Rectangle.cs
src/Tizen.Multimedia/Common/Size.cs
src/Tizen.Multimedia/Common/ValdiationUtil.cs
src/Tizen.Multimedia/Common/Visibility.cs [moved from src/Tizen.Multimedia/MediaVision/TextAttribute.cs with 86% similarity, mode: 0644]
src/Tizen.Multimedia/Interop/Interop.MediaVision.BarCode.cs
src/Tizen.Multimedia/Interop/Interop.MediaVision.Common.cs
src/Tizen.Multimedia/Interop/Interop.MediaVision.Face.cs
src/Tizen.Multimedia/Interop/Interop.MediaVision.Image.cs
src/Tizen.Multimedia/Interop/Interop.MediaVision.Surveillance.cs
src/Tizen.Multimedia/MediaVision/Barcode.cs
src/Tizen.Multimedia/MediaVision/BarcodeDetectionConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/BarcodeDetectionTarget.cs [moved from src/Tizen.Multimedia/MediaVision/TargetAttribute.cs with 85% similarity, mode: 0644]
src/Tizen.Multimedia/MediaVision/BarcodeDetector.cs
src/Tizen.Multimedia/MediaVision/BarcodeDetectorEngineConfiguration.cs [deleted file]
src/Tizen.Multimedia/MediaVision/BarcodeGenerationConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/BarcodeGenerator.cs
src/Tizen.Multimedia/MediaVision/BarcodeGeneratorEngineConfiguration.cs [deleted file]
src/Tizen.Multimedia/MediaVision/BarcodeImageConfiguration.cs
src/Tizen.Multimedia/MediaVision/BarcodeImageFormat.cs
src/Tizen.Multimedia/MediaVision/BarcodeType.cs
src/Tizen.Multimedia/MediaVision/Colorspace.cs
src/Tizen.Multimedia/MediaVision/EngineConfiguration.cs
src/Tizen.Multimedia/MediaVision/ErrorCorrectionLevel.cs
src/Tizen.Multimedia/MediaVision/EyeCondition.cs
src/Tizen.Multimedia/MediaVision/FaceDetectionConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/FaceDetector.cs
src/Tizen.Multimedia/MediaVision/FaceEngineConfiguration.cs [deleted file]
src/Tizen.Multimedia/MediaVision/FaceRecognitionConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/FaceRecognitionModel.cs
src/Tizen.Multimedia/MediaVision/FaceRecognitionModelType.cs
src/Tizen.Multimedia/MediaVision/FaceRecognitionResult.cs
src/Tizen.Multimedia/MediaVision/FaceRecognizer.cs
src/Tizen.Multimedia/MediaVision/FaceTracker.cs
src/Tizen.Multimedia/MediaVision/FaceTrackingModel.cs
src/Tizen.Multimedia/MediaVision/FaceTrackingResult.cs
src/Tizen.Multimedia/MediaVision/FacialExpression.cs
src/Tizen.Multimedia/MediaVision/Image.cs [deleted file]
src/Tizen.Multimedia/MediaVision/ImageEngineConfiguration.cs [deleted file]
src/Tizen.Multimedia/MediaVision/ImageFillConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/ImageObject.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/ImageRecognitionConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/ImageRecognitionResult.cs
src/Tizen.Multimedia/MediaVision/ImageRecognizer.cs
src/Tizen.Multimedia/MediaVision/ImageTracker.cs
src/Tizen.Multimedia/MediaVision/ImageTrackingConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/ImageTrackingModel.cs
src/Tizen.Multimedia/MediaVision/MediaVisionError.cs [moved from src/Tizen.Multimedia/MediaVision/MediaVisionErrorFactory.cs with 66% similarity, mode: 0644]
src/Tizen.Multimedia/MediaVision/MediaVisionSource.cs
src/Tizen.Multimedia/MediaVision/MovementDetectedEventArgs.cs
src/Tizen.Multimedia/MediaVision/MovementDetectionConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/MovementDetectionEventTrigger.cs [deleted file]
src/Tizen.Multimedia/MediaVision/MovementDetector.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/PersonAppearanceChangedEventArgs.cs [deleted file]
src/Tizen.Multimedia/MediaVision/PersonAppearanceDetectedEventArgs.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/PersonAppearanceDetectionConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/PersonAppearanceDetector.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/PersonAppearanceEventTrigger.cs [deleted file]
src/Tizen.Multimedia/MediaVision/PersonRecognitionConfiguration.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/PersonRecognitionEventTrigger.cs [deleted file]
src/Tizen.Multimedia/MediaVision/PersonRecognitionInfo.cs [moved from src/Tizen.Multimedia/MediaVision/PersonRecognitionResult.cs with 53% similarity, mode: 0644]
src/Tizen.Multimedia/MediaVision/PersonRecognizedEventArgs.cs
src/Tizen.Multimedia/MediaVision/PersonRecognizer.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/QrConfiguration.cs
src/Tizen.Multimedia/MediaVision/QrMode.cs
src/Tizen.Multimedia/MediaVision/Quadrangle.cs
src/Tizen.Multimedia/MediaVision/SurveillanceConfiguration.cs [moved from src/Tizen.Multimedia/MediaVision/FaceDetectionResult.cs with 66% similarity, mode: 0644]
src/Tizen.Multimedia/MediaVision/SurveillanceEngine.cs [new file with mode: 0644]
src/Tizen.Multimedia/MediaVision/SurveillanceEngineConfiguration.cs [deleted file]
src/Tizen.Multimedia/MediaVision/SurveillanceEventTrigger.cs [deleted file]
src/Tizen.Multimedia/MediaVision/SurveillanceSource.cs [new file with mode: 0644]

index 2b11b07..7556c91 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       csapi-multimedia
 Summary:    Tizen Multimedia API for C#
-Version:    1.0.42
+Version:    1.0.43
 Release:    0
 Group:      Development/Libraries
 License:    Apache-2.0
diff --git a/src/Tizen.Multimedia/Common/IBufferOwner.cs b/src/Tizen.Multimedia/Common/IBufferOwner.cs
new file mode 100644 (file)
index 0000000..f779510
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    internal enum MediaBufferAccessMode
+    {
+        Read,
+        Write
+    }
+
+    internal interface IBufferOwner
+    {
+        bool IsBufferAccessible(object buffer, MediaBufferAccessMode accessMode);
+
+        bool IsDisposed { get; }
+    }
+
+
+    internal static class BufferOwnerExtensions
+    {
+        internal static void ValidateBufferReadable(this IBufferOwner bufferOwner, IReadOnlyBuffer buffer)
+        {
+            if (bufferOwner.IsDisposed)
+            {
+                throw new ObjectDisposedException(bufferOwner.GetType().Name);
+            }
+
+            if (!bufferOwner.IsBufferAccessible(buffer, MediaBufferAccessMode.Read))
+            {
+                throw new InvalidOperationException("The buffer is not in the readable state.");
+            }
+        }
+
+        internal static void ValidateBufferWritable(this IBufferOwner bufferOwner, IMediaBuffer buffer)
+        {
+            if (bufferOwner.IsDisposed)
+            {
+                throw new ObjectDisposedException(bufferOwner.GetType().Name);
+            }
+
+            if (!bufferOwner.IsBufferAccessible(buffer, MediaBufferAccessMode.Write))
+            {
+                throw new InvalidOperationException("The buffer is not in writable state.");
+            }
+        }
+    }
+
+}
diff --git a/src/Tizen.Multimedia/Common/IMediaBuffer.cs b/src/Tizen.Multimedia/Common/IMediaBuffer.cs
new file mode 100644 (file)
index 0000000..a922efc
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Tizen.Multimedia
+{
+    public interface IReadOnlyBuffer
+    {
+        /// <summary>
+        /// Gets or sets a value at the specified index.
+        /// </summary>
+        /// <param name="index">The index of the value to get or set.</param>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     index is less than zero.
+        ///     <para>-or-</para>
+        ///     index is equal to or greater than <see cref="Length"/>.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The object that owns the current buffer already has been disposed of.</exception>
+        /// <exception cref="InvalidOperationException">The buffer is not available. i.e. not writable state.</exception>
+        byte this[int index]
+        {
+            get;
+        }
+        /// <summary>
+        /// Gets the size of the buffer, in bytes.
+        /// </summary>
+        int Length
+        {
+            get;
+        }
+
+        /// <summary>
+        /// Copies data from a byte array to the buffer.
+        /// </summary>
+        /// <param name="source">The array to copy from.</param>
+        /// <param name="startIndex">The zero-based index in the source array where copying should start.</param>
+        /// <param name="length">The number of array elements to copy.</param>
+        /// <exception cref="ArgumentOutOfRangeException">startIndex or length is not valid.</exception>
+        /// <exception cref="ObjectDisposedException">The object that owns the current buffer already has been disposed of.</exception>
+        void CopyTo(byte[] dest, int startIndex, int length);
+
+        /// <summary>
+        /// Copies data from a byte array to the buffer.
+        /// </summary>
+        /// <param name="source">The array to copy from.</param>
+        /// <param name="startIndex">The zero-based index in the source array where copying should start.</param>
+        /// <param name="length">The number of array elements to copy.</param>
+        /// <param name="offset">The zero-based index in the buffer where copying should start.</param>
+        /// <exception cref="ArgumentOutOfRangeException">startIndex, offset or length is not valid.</exception>
+        /// <exception cref="ObjectDisposedException">The object that owns the current buffer already has been disposed of.</exception>
+        void CopyTo(byte[] dest, int startIndex, int length, int offset);
+    }
+
+    public interface IMediaBuffer : IReadOnlyBuffer
+    {
+        /// <summary>
+        /// Gets or sets a value at the specified index.
+        /// </summary>
+        /// <param name="index">The index of the value to get or set.</param>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     index is less than zero.
+        ///     <para>-or-</para>
+        ///     index is equal to or greater than <see cref="Length"/>.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">The object that owns the current buffer already has been disposed of.</exception>
+        /// <exception cref="InvalidOperationException">The buffer is not available. i.e. not writable state.</exception>
+        byte this[int index]
+        {
+            get;
+            set;
+        }
+        /// <summary>
+        /// Copies data from the buffer to a byte array.
+        /// </summary>
+        /// <param name="dest">The array to copy to.</param>
+        /// <param name="startIndex">The zero-based index in the dest array where copying should start.</param>
+        /// <param name="length">The number of elements to copy.</param>
+        /// <exception cref="ArgumentOutOfRangeException">startIndex or length is not valid.</exception>
+        /// <exception cref="ObjectDisposedException">The object that owns the current buffer already has been disposed of.</exception>
+        /// <exception cref="InvalidOperationException">The buffer is not available. i.e. not writable state.</exception>
+
+        void CopyFrom(byte[] source, int startIndex, int length);
+
+        /// <summary>
+        /// Copies data from the buffer to a byte array.
+        /// </summary>
+        /// <param name="dest">The array to copy to.</param>
+        /// <param name="startIndex">The zero-based index in the dest array where copying should start.</param>
+        /// <param name="length">The number of elements to copy.</param>
+        /// <param name="offset">The zero-based index in the buffer where copying should start.</param>
+        /// <exception cref="ArgumentOutOfRangeException">startIndex, offset or length is not valid.</exception>
+        /// <exception cref="ObjectDisposedException">The object that owns the current buffer already has been disposed of.</exception>
+        /// <exception cref="InvalidOperationException">The buffer is not available. i.e. not writable state.</exception>
+        void CopyFrom(byte[] source, int startIndex, int length, int offset);
+
+    }
+
+    /// <summary>
+    /// Represents a buffer for a <see cref="MediaPacket"/>.
+    /// </summary>
+    internal class DependentMediaBuffer : IMediaBuffer
+    {
+        private readonly IBufferOwner _owner;
+        private readonly IntPtr _dataHandle;
+
+        internal DependentMediaBuffer(IBufferOwner owner, IntPtr dataHandle, int size)
+        {
+            Debug.Assert(owner != null, "Owner is null!");
+            Debug.Assert(!owner.IsDisposed, "Owner has been already disposed!");
+            Debug.Assert(dataHandle != IntPtr.Zero, "dataHandle is null!");
+            Debug.Assert(size >= 0, "size must not be negative!");
+
+            _owner = owner;
+            _dataHandle = dataHandle;
+            Length = size;
+        }
+
+        public byte this[int index]
+        {
+            get
+            {
+                _owner.ValidateBufferReadable(this);
+
+                if (index < 0 || index >= Length)
+                {
+                    throw new ArgumentOutOfRangeException($"Valid index range is [0, { nameof(Length) }).");
+                }
+
+                return Marshal.ReadByte(_dataHandle, index);
+            }
+            set
+            {
+                _owner.ValidateBufferWritable(this);
+
+                Marshal.WriteByte(_dataHandle, index, value);
+            }
+        }
+
+        /// <summary>
+        /// Validates the range
+        /// </summary>
+        /// <param name="offset"></param>
+        /// <param name="length"></param>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     offset + length is greater than <see cref="Length"/>.
+        ///     <para>-or-</para>
+        ///     offset or length is less than zero.
+        /// </exception>
+        private void ValidateRange(int offset, int length)
+        {
+            if (offset + length > Length)
+            {
+                throw new ArgumentOutOfRangeException("offset + length can't be greater than length of the buffer.");
+            }
+            if (length < 0)
+            {
+                throw new ArgumentOutOfRangeException($"Length can't be less than zero : { length }.");
+            }
+            if (offset < 0)
+            {
+                throw new ArgumentOutOfRangeException($"Offset can't be less than zero : { offset }.");
+            }
+        }
+
+        public void CopyFrom(byte[] source, int startIndex, int length, int offset)
+        {
+            _owner.ValidateBufferReadable(this);
+
+            if (startIndex < 0)
+            {
+                throw new ArgumentOutOfRangeException("startIndex can't be less than zero.");
+            }
+            if (startIndex + length > source.Length)
+            {
+                throw new ArgumentOutOfRangeException("startIndex + length can't be greater than source.Length.");
+            }
+
+            ValidateRange(offset, length);
+
+            Marshal.Copy(source, startIndex, IntPtr.Add(_dataHandle, offset), length);
+        }
+
+        public void CopyFrom(byte[] source, int startIndex, int length)
+        {
+            CopyFrom(source, startIndex, length, 0);
+        }
+
+         public void CopyTo(byte[] dest, int startIndex, int length, int offset)
+        {
+            _owner.ValidateBufferWritable(this);
+
+            if (startIndex < 0)
+            {
+                throw new ArgumentOutOfRangeException("Start index can't be less than zero.");
+            }
+            if (startIndex + length > dest.Length)
+            {
+                throw new ArgumentOutOfRangeException("startIndex + length can't be greater than dest.Length.");
+            }
+
+            ValidateRange(offset, length);
+
+            Marshal.Copy(IntPtr.Add(_dataHandle, offset), dest, startIndex, length);
+        }
+
+        public void CopyTo(byte[] dest, int startIndex, int length)
+        {
+            CopyTo(dest, startIndex, length, 0);
+        }
+
+        public int Length { get; }
+    }
+}
diff --git a/src/Tizen.Multimedia/Common/MultimediaLog.cs b/src/Tizen.Multimedia/Common/MultimediaLog.cs
new file mode 100644 (file)
index 0000000..e844bdd
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace Tizen.Multimedia
+{
+    internal static class MultimediaLog
+    {
+        [Conditional("DEBUG")]
+        public static void Debug(string tag, string message, Exception e = null, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
+        {
+            Log.Debug(tag, BuildMessage(message, e), file, func, line);
+        }
+
+        public static void Error(string tag, string message, Exception e = null, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
+        {
+            Log.Error(tag, BuildMessage(message, e), file, func, line);
+        }
+
+        public static void Fatal(string tag, string message, Exception e = null, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
+        {
+            Log.Fatal(tag, BuildMessage(message, e), file, func, line);
+        }
+
+        public static void Info(string tag, string message, Exception e = null, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
+        {
+            Log.Info(tag, BuildMessage(message, e), file, func, line);
+        }
+
+        public static void Verbose(string tag, string message, Exception e = null, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
+        {
+            Log.Verbose(tag, BuildMessage(message, e), file, func, line);
+        }
+
+        public static void Warn(string tag, string message, Exception e = null, [CallerFilePath] string file = "", [CallerMemberName] string func = "", [CallerLineNumber] int line = 0)
+        {
+            Log.Warn(tag, BuildMessage(message, e), file, func, line);
+        }
+
+        private static string BuildMessage(string message, Exception exception)
+        {
+            if (exception == null)
+            {
+                return message;
+            }
+
+            StringBuilder sb = new StringBuilder();
+
+            Exception e = exception;
+            while (e != null)
+            {
+                message += e.Message + Environment.NewLine + e.StackTrace;
+                e = e.InnerException;
+            }
+
+            return sb.ToString();
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/Common/ObjectKeeper.cs b/src/Tizen.Multimedia/Common/ObjectKeeper.cs
new file mode 100644 (file)
index 0000000..6f4de80
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Tizen.Multimedia
+{
+    internal abstract class ObjectKeeper : IDisposable
+    {
+        private ObjectKeeper()
+        {
+        }
+
+        public abstract void Dispose();
+
+        public static ObjectKeeperImpl<T> Get<T>(T target)
+        {
+            return new ObjectKeeperImpl<T>(target);
+        }
+
+        internal class ObjectKeeperImpl<T> : ObjectKeeper
+        {
+            private readonly GCHandle _handle;
+
+            internal ObjectKeeperImpl(T obj)
+            {
+                Target = obj;
+                _handle = GCHandle.Alloc(obj);
+            }
+
+            ~ObjectKeeperImpl()
+            {
+                Dispose(false);
+            }
+
+            private bool disposedValue = false;
+
+            protected virtual void Dispose(bool disposing)
+            {
+                if (!disposedValue)
+                {
+                    if (disposing)
+                    {
+                        _handle.Free();
+                    }
+
+                    disposedValue = true;
+                }
+            }
+
+            public override void Dispose()
+            {
+                Dispose(true);
+                GC.SuppressFinalize(this);
+            }
+
+            public T Target
+            {
+                get;
+            }
+        }
+    }
+}
index 3866788..9ac20fe 100644 (file)
@@ -51,7 +51,7 @@ namespace Tizen.Multimedia
             set;
         }
 
-        public override string ToString() => $"X={X}, Y={Y}";
+        public override string ToString() => $"X={X.ToString()}, Y={Y.ToString()}";
 
         public override int GetHashCode()
         {
@@ -60,23 +60,17 @@ namespace Tizen.Multimedia
 
         public override bool Equals(object obj)
         {
-            if ((obj is Point) == false)
-            {
-                return false;
-            }
-
-            Point rhs = (Point)obj;
-            return X == rhs.X && Y == rhs.Y;
+            return obj is Point && this == (Point)obj;
         }
 
         public static bool operator ==(Point lhs, Point rhs)
         {
-            return lhs.Equals(rhs);
+            return lhs.X == rhs.X && lhs.Y == rhs.Y;
         }
 
         public static bool operator !=(Point lhs, Point rhs)
         {
-            return !lhs.Equals(rhs);
+            return !(lhs == rhs);
         }
     }
 }
index e10f724..cc82a74 100644 (file)
@@ -28,9 +28,10 @@ namespace Tizen.Multimedia
         /// </summary>
         /// <param name="min">Minimum value of the range.</param>
         /// <param name="max">Maximum value of the range.</param>
+        /// <exception cref="ArgumentException"><paramref name="max"/> is less than <paramref name="min"/>.</exception>
         public Range(int min, int max)
         {
-            if (min > max )
+            if (min > max)
             {
                 throw new ArgumentException($"min can't be greater than max.");
             }
@@ -71,7 +72,7 @@ namespace Tizen.Multimedia
             return Min <= value && value <= Max;
         }
 
-        public override string ToString() => $"Min={Min}, Max={Max}";
+        public override string ToString() => $"Min={Min.ToString()}, Max={Max.ToString()}";
 
         public override int GetHashCode()
         {
@@ -80,13 +81,17 @@ namespace Tizen.Multimedia
 
         public override bool Equals(object obj)
         {
-            if ((obj is Range) == false)
-            {
-                return false;
-            }
+            return obj is Range && this == (Range)obj;
+        }
 
-            Range rhs = (Range)obj;
-            return Min == rhs.Min && Max == rhs.Max;
+        public static bool operator ==(Range lhs, Range rhs)
+        {
+            return lhs.Min == rhs.Min && lhs.Max == rhs.Max;
+        }
+
+        public static bool operator !=(Range lhs, Range rhs)
+        {
+            return !(lhs == rhs);
         }
     }
 }
index c31fd28..40b5b52 100644 (file)
 
 namespace Tizen.Multimedia
 {
-    // TODO consider changing it to struct
     /// <summary>
     /// This class represents location of the object bounded by rectangle defined by
     /// coordinates of top left corner, width and height.
     /// </summary>
-    public class Rectangle
+    public struct Rectangle
     {
         private Point _location;
         private Size _size;
 
         /// <summary>
-        /// Initializes a new instance of the Rectangle with default values.
-        /// </summary>
-        public Rectangle() : this(new Point(), new Size())
-        {
-        }
-
-        /// <summary>
         /// Initializes a new instance of the Rectangle with the specified values.
         /// </summary>
         /// <param name="x">The x-coordinate of the upper-left corner of the rectangle.</param>
@@ -48,7 +40,7 @@ namespace Tizen.Multimedia
         /// <summary>
         /// Initializes a new instance of the Rectangle with the specified values.
         /// </summary>
-        /// <param name="location">A <see cref="Point"/> that represents the upper-left corner of the rectangular region.</param>
+        /// <param name="location">A <see cref="Location"/> that represents the upper-left corner of the rectangular region.</param>
         /// <param name="size">A <see cref="Size"/> that represents the width and height of the rectangular region.</param>
         public Rectangle(Point location, Size size)
         {
@@ -56,11 +48,10 @@ namespace Tizen.Multimedia
             _size = size;
         }
 
-        //TODO rename
         /// <summary>
         /// Gets or sets the coordinates of the upper-left corner of the rectangle.
         /// </summary>
-        public Point Point
+        public Point Location
         {
             get { return _location; }
             set { _location = value; }
@@ -71,7 +62,7 @@ namespace Tizen.Multimedia
         /// </summary>
         public int X
         {
-            get { return Point.X; }
+            get { return _location.X; }
             set { _location.X = value; }
         }
 
@@ -80,7 +71,7 @@ namespace Tizen.Multimedia
         /// </summary>
         public int Y
         {
-            get { return Point.Y; }
+            get { return _location.Y; }
             set { _location.Y = value; }
         }
 
@@ -111,33 +102,26 @@ namespace Tizen.Multimedia
             set { _size = value; }
         }
 
-        public override string ToString() => $"{_location}, {_size}";
-
+        public override string ToString() => $"{_location.ToString()}, {_size.ToString()}";
 
         public override int GetHashCode()
         {
-            return new { Point, Size }.GetHashCode();
+            return new { Location, Size }.GetHashCode();
         }
 
         public override bool Equals(object obj)
         {
-            if ((obj is Rectangle) == false)
-            {
-                return false;
-            }
-
-            Rectangle rhs = (Rectangle)obj;
-            return Point == rhs.Point && Size == rhs.Size;
+            return obj is Rectangle && this == (Rectangle)obj;
         }
 
         public static bool operator ==(Rectangle lhs, Rectangle rhs)
         {
-            return lhs.Equals(rhs);
+            return lhs.Location == rhs.Location && lhs.Size == rhs.Size;
         }
 
         public static bool operator !=(Rectangle lhs, Rectangle rhs)
         {
-            return !lhs.Equals(rhs);
+            return !(lhs == rhs);
         }
     }
 }
index 30ff0b0..b7bbb5a 100644 (file)
@@ -47,7 +47,7 @@ namespace Tizen.Multimedia
             set;
         }
 
-        public override string ToString() => $"Width={ Width }, Height={ Height }";
+        public override string ToString() => $"Width={ Width.ToString() }, Height={ Height.ToString() }";
 
         public override int GetHashCode()
         {
@@ -56,23 +56,17 @@ namespace Tizen.Multimedia
 
         public override bool Equals(object obj)
         {
-            if ((obj is Size) == false)
-            {
-                return false;
-            }
-
-            Size rhs = (Size)obj;
-            return Width == rhs.Width && Height == rhs.Height;
+            return obj is Size && this == (Size)obj;
         }
 
         public static bool operator ==(Size lhs, Size rhs)
         {
-            return lhs.Equals(rhs);
+            return lhs.Width == rhs.Width && lhs.Height == rhs.Height;
         }
 
         public static bool operator !=(Size lhs, Size rhs)
         {
-            return !lhs.Equals(rhs);
+            return !(lhs == rhs);
         }
     }
 }
index 9e7dcfb..f63913b 100644 (file)
@@ -27,5 +27,12 @@ namespace Tizen.Multimedia
                 throw new ArgumentException($"Invalid { enumType.Name } value : { value }");
             }
         }
+        internal static void ValidateEnum(Type enumType, object value, string paramName)
+        {
+            if (!Enum.IsDefined(enumType, value))
+            {
+                throw new ArgumentException($"Invalid { enumType.Name } value : { value }", paramName);
+            }
+        }
     }
 }
old mode 100755 (executable)
new mode 100644 (file)
similarity index 86%
rename from src/Tizen.Multimedia/MediaVision/TextAttribute.cs
rename to src/Tizen.Multimedia/Common/Visibility.cs
index 1f43e0c..11d19c6
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -19,7 +19,7 @@ namespace Tizen.Multimedia
     /// <summary>
     /// Enumeration to text attribute
     /// </summary>
-    public enum TextAttribute
+    public enum Visibility
     {
         /// <summary>
         /// Invisible
@@ -28,10 +28,6 @@ namespace Tizen.Multimedia
         /// <summary>
         /// Visible
         /// </summary>
-        Visible,
-        /// <summary>
-        /// Unavailable
-        /// </summary>
-        Unavailable
+        Visible
     }
 }
index fd60193..03a0013 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -31,25 +31,38 @@ internal static partial class Interop
         /// <summary>
         /// Interop for barcode detector APIs
         /// </summary>
-        internal static partial class BarCodeDetector
+        internal static partial class BarcodeDetector
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_barcode_detect")]
-            internal static extern int Detect(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, Rectangle roi, MvBarcodeDetectedCallback detectCb, IntPtr /* void */ userData);
+            internal static extern MediaVisionError Detect(IntPtr source, IntPtr engineCfg, Rectangle roi,
+                DetectedCallback detectCb, IntPtr userData = default(IntPtr));
 
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvBarcodeDetectedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr barcodeLocations, IntPtr messages, IntPtr /* mv_barcode_type_e */ types, int numberOfBarcodes, IntPtr /* void */ userData);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void DetectedCallback(
+                IntPtr source,
+                IntPtr engineCfg,
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)]
+                Quadrangle[] locations,
+                [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 5)]
+                string[] messages,
+                BarcodeType[] types,
+                int numberOfBarcodes,
+                IntPtr userData);
         }
 
         /// <summary>
         /// Interop for barcode generator APIs
         /// </summary>
-        internal static partial class BarCodeGenerator
+        internal static partial class BarcodeGenerator
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_barcode_generate_source")]
-            internal static extern int GenerateSource(IntPtr /* mv_engine_config_h */ engineCfg, string message, BarcodeType /* mv_barcode_type_e */ type, QrMode /* mv_barcode_qr_mode_e */ qrEncMode, ErrorCorrectionLevel /* mv_barcode_qr_ecc_e */ qrEcc, int qrVersion, IntPtr /* mv_source_h */ image);
+            internal static extern MediaVisionError GenerateSource(IntPtr engineCfg, string message,
+                BarcodeType type, int qrEncMode, int qrEcc, int qrVersion, IntPtr source);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_barcode_generate_image")]
-            internal static extern int GenerateImage(IntPtr /* mv_engine_config_h */ engineCfg, string message, int imageWidth, int imageHeight, BarcodeType /* mv_barcode_type_e */ type, QrMode /* mv_barcode_qr_mode_e */ qrEncMode, ErrorCorrectionLevel /* mv_barcode_qr_ecc_e */ qrEcc, int qrVersion, string imagePath, BarcodeImageFormat /* mv_barcode_image_format_e */ imageFormat);
+            internal static extern MediaVisionError GenerateImage(IntPtr engineCfg,
+                string message, int imageWidth, int imageHeight, BarcodeType type,
+                int qrEncMode, int qrEcc, int qrVersion, string imagePath, BarcodeImageFormat imageFormat);
         }
     }
 }
index bb93798..1ee91a0 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 
 using System;
 using System.Runtime.InteropServices;
+using Tizen.Multimedia;
 
 /// <summary>
 /// Interop APIs
 /// </summary>
 internal static partial class Interop
 {
+    internal static Tizen.Multimedia.Point ToApiStruct(this MediaVision.Point pt)
+    {
+        return new Tizen.Multimedia.Point(pt.x, pt.y);
+    }
+
+    internal static MediaVision.Point ToMarshalable(this Tizen.Multimedia.Point pt)
+    {
+        return new MediaVision.Point() { x = pt.X, y = pt.Y };
+    }
+
+    internal static MediaVision.Point[] ToMarshalable(Tizen.Multimedia.Point[] pts)
+    {
+        var result = new MediaVision.Point[pts.Length];
+        for (int i = 0; i < pts.Length;++i)
+        {
+            result[i] = pts[i].ToMarshalable();
+        }
+        return result;
+    }
+
+
+    internal static Tizen.Multimedia.Quadrangle ToApiStruct(this MediaVision.Quadrangle quadrangle)
+    {
+        Tizen.Multimedia.Point[] points = new Tizen.Multimedia.Point[4];
+        for (int i = 0; i < 4; ++i)
+        {
+            points[i] = quadrangle.points[i].ToApiStruct();
+        }
+        return new Tizen.Multimedia.Quadrangle(points);
+    }
+
+    internal static MediaVision.Quadrangle ToMarshalable(this Tizen.Multimedia.Quadrangle quadrangle)
+    {
+        MediaVision.Point[] points = new MediaVision.Point[4];
+        for (int i = 0; i < 4; ++i)
+        {
+            points[i] = quadrangle.Points[i].ToMarshalable();
+        }
+        return new MediaVision.Quadrangle() { points = points };
+    }
+
+    internal static Tizen.Multimedia.Rectangle ToApiStruct(this MediaVision.Rectangle rectangle)
+    {
+        return new Tizen.Multimedia.Rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+    }
+
+    internal static MediaVision.Rectangle ToMarshalable(this Tizen.Multimedia.Rectangle rectangle)
+    {
+        return new MediaVision.Rectangle()
+        {
+            x = rectangle.X,
+            y = rectangle.Y,
+            width = rectangle.Width,
+            height = rectangle.Height
+        };
+    }
+
+    internal static Tizen.Multimedia.Rectangle[] ToApiStruct(MediaVision.Rectangle[] rects)
+    {
+        var result = new Tizen.Multimedia.Rectangle[rects.Length];
+
+        for (int i = 0; i < rects.Length; i++)
+        {
+            result[i] = rects[i].ToApiStruct();
+        }
+        return result;
+    }
+
     /// <summary>
     /// Interop for media vision APIs
     /// </summary>
@@ -32,7 +101,7 @@ internal static partial class Interop
         {
             internal int x;
             internal int y;
-        };
+        }
 
         [StructLayout(LayoutKind.Sequential)]
         internal struct Rectangle
@@ -41,16 +110,14 @@ internal static partial class Interop
             internal int y;
             internal int width;
             internal int height;
-        };
+        }
 
         [StructLayout(LayoutKind.Sequential)]
         internal struct Quadrangle
         {
-            internal int x1, y1;
-            internal int x2, y2;
-            internal int x3, y3;
-            internal int x4, y4;
-        };
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+            internal Point[] points;
+        }
 
         /// <summary>
         /// Interop for media vision source APIs
@@ -58,28 +125,29 @@ internal static partial class Interop
         internal static partial class MediaSource
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_create_source")]
-            internal static extern int Create(out IntPtr /* mv_source_h */ source);
+            internal static extern MediaVisionError Create(out IntPtr source);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_destroy_source")]
             internal static extern int Destroy(IntPtr /* mv_source_h */ source);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_source_fill_by_media_packet")]
-            internal static extern int FillMediaPacket(IntPtr /* mv_source_h */ source, IntPtr /* media_packet_h */ mediaPacket);
+            internal static extern MediaVisionError FillMediaPacket(IntPtr source, IntPtr mediaPacket);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_source_fill_by_buffer")]
-            internal static extern int FillBuffer(IntPtr /* mv_source_h */ source, byte[] buffer, int bufferSize, uint imageWidth, uint imageHeight, Tizen.Multimedia.Colorspace colorspace);
+            internal static extern MediaVisionError FillBuffer(IntPtr source, byte[] buffer,
+                int bufferSize, uint imageWidth, uint imageHeight, Colorspace colorspace);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_source_clear")]
             internal static extern int Clear(IntPtr /* mv_source_h */ source);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_source_get_buffer")]
-            internal static extern int GetBuffer(IntPtr /* mv_source_h */ source, out IntPtr buffer, out int bufferSize);
+            internal static extern MediaVisionError GetBuffer(IntPtr source, out IntPtr buffer, out int bufferSize);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_source_get_height")]
-            internal static extern int GetHeight(IntPtr /* mv_source_h */ source, out uint imageHeight);
+            internal static extern int GetHeight(IntPtr source, out uint imageHeight);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_source_get_width")]
-            internal static extern int GetWidth(IntPtr /* mv_source_h */ source, out uint imageWidth);
+            internal static extern int GetWidth(IntPtr source, out uint imageWidth);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_source_get_colorspace")]
             internal static extern int GetColorspace(IntPtr /* mv_source_h */ source, out Tizen.Multimedia.Colorspace colorspace);
@@ -91,34 +159,34 @@ internal static partial class Interop
         internal static partial class EngineConfig
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_create_engine_config")]
-            internal static extern int Create(out IntPtr /* mv_engine_config_h */ engineConfig);
+            internal static extern MediaVisionError Create(out IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_destroy_engine_config")]
-            internal static extern int Destroy(IntPtr /* mv_engine_config_h */ engineConfig);
+            internal static extern int Destroy(IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_set_double_attribute")]
-            internal static extern int SetDouble(IntPtr /* mv_engine_config_h */ source, string name, double value);
+            internal static extern Tizen.Multimedia.MediaVisionError SetDouble(IntPtr handle, string name, double value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_set_int_attribute")]
-            internal static extern int SetInt(IntPtr /* mv_engine_config_h */ source, string name, int value);
+            internal static extern Tizen.Multimedia.MediaVisionError SetInt(IntPtr handle, string name, int value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_set_bool_attribute")]
-            internal static extern int SetBool(IntPtr /* mv_engine_config_h */ source, string name, bool value);
+            internal static extern Tizen.Multimedia.MediaVisionError SetBool(IntPtr handle, string name, bool value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_set_string_attribute")]
-            internal static extern int SetString(IntPtr /* mv_engine_config_h */ source, string name, string value);
+            internal static extern Tizen.Multimedia.MediaVisionError SetString(IntPtr handle, string name, string value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_get_double_attribute")]
-            internal static extern int GetDouble(IntPtr /* mv_engine_config_h */ source, string name, out double value);
+            internal static extern Tizen.Multimedia.MediaVisionError GetDouble(IntPtr handle, string name, out double value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_get_int_attribute")]
-            internal static extern int GetInt(IntPtr /* mv_engine_config_h */ source, string name, out int value);
+            internal static extern Tizen.Multimedia.MediaVisionError GetInt(IntPtr handle, string name, out int value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_get_bool_attribute")]
-            internal static extern int GetBool(IntPtr /* mv_engine_config_h */ source, string name, out bool value);
+            internal static extern Tizen.Multimedia.MediaVisionError GetBool(IntPtr handle, string name, out bool value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_engine_config_get_string_attribute")]
-            internal static extern int GetString(IntPtr /* mv_engine_config_h */ source, string name, out string value);
+            internal static extern Tizen.Multimedia.MediaVisionError GetString(IntPtr handle, string name, out IntPtr value);
         }
     }
 }
index cdd065c..224caa8 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -34,34 +34,50 @@ internal static partial class Interop
         internal static partial class Face
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_detect")]
-            internal static extern int Detect(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, MvFaceDetectedCallback detectedCb, IntPtr /* void */ userData);
+            internal static extern MediaVisionError Detect(IntPtr source, IntPtr engineCfg,
+                DetectedCallback detectedCb, IntPtr userData = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognize")]
-            internal static extern int Recognize(IntPtr /* mv_source_h */ source, IntPtr /* mv_face_recognition_model_h */ recognitionModel, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr faceLocation, MvFaceRecognizedCallback recognizedCb, IntPtr /* void */ userData);
+            internal static extern MediaVisionError Recognize(IntPtr source, IntPtr recognitionModel, IntPtr engineCfg,
+                IntPtr faceLocation, RecognizedCallback recognizedCb, IntPtr userData = default(IntPtr));
+
+            [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognize")]
+            internal static extern MediaVisionError Recognize(IntPtr source, IntPtr recognitionModel, IntPtr engineCfg,
+                ref Rectangle faceLocation, RecognizedCallback recognizedCb, IntPtr userData = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_track")]
-            internal static extern int Track(IntPtr /* mv_source_h */ source, IntPtr /* mv_face_tracking_model_h */ trackingModel, IntPtr /* mv_engine_config_h */ engineCfg, MvFaceTrackedCallback trackedCb, bool doLearn, IntPtr /* void */ userData);
+            internal static extern MediaVisionError Track(IntPtr source, IntPtr trackingModel, IntPtr engineCfg,
+                TrackedCallback trackedCb, bool doLearn, IntPtr userData = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_eye_condition_recognize")]
-            internal static extern int RecognizeEyeCondition(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, Rectangle faceLocation, MvFaceEyeConditionRecognizedCallback eyeConditionRecognizedCb, IntPtr /* void */ userData);
+            internal static extern MediaVisionError RecognizeEyeCondition(IntPtr source, IntPtr engineCfg,
+                Rectangle faceLocation, EyeConditionRecognizedCallback eyeConditionRecognizedCb, IntPtr userData = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_facial_expression_recognize")]
-            internal static extern int RecognizeFacialExpression(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, Rectangle faceLocation, MvFaceFacialExpressionRecognizedCallback expressionRecognizedCb, IntPtr /* void */ userData);
-
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvFaceDetectedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr facesLocations, int numberOfFaces, IntPtr /* void */ userData);
-
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvFaceRecognizedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_face_recognition_model_h */ recognitionModel, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr faceLocation, IntPtr faceLabel, double confidence, IntPtr /* void */ userData);
-
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvFaceTrackedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_face_tracking_model_h */ trackingModel, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr location, double confidence, IntPtr /* void */ userData);
-
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvFaceEyeConditionRecognizedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, Rectangle faceLocation, EyeCondition /* mv_face_eye_condition_e */ eyeCondition, IntPtr /* void */ userData);
-
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvFaceFacialExpressionRecognizedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, Rectangle faceLocation, FacialExpression /* mv_face_facial_expression_e */ facialExpression, IntPtr /* void */ userData);
+            internal static extern MediaVisionError RecognizeFacialExpression(IntPtr source, IntPtr engineCfg,
+                Rectangle faceLocation, MvFaceFacialExpressionRecognizedCallback expressionRecognizedCb,
+                IntPtr userData = default(IntPtr));
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void DetectedCallback(IntPtr source, IntPtr engineCfg,
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] Rectangle[] facesLocations,
+                int numberOfFaces, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void RecognizedCallback(IntPtr source, IntPtr recognitionModel,
+                IntPtr engineCfg, IntPtr faceLocation, IntPtr faceLabel, double confidence, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void TrackedCallback(IntPtr source, IntPtr trackingModel, IntPtr engineCfg,
+                IntPtr location, double confidence, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void EyeConditionRecognizedCallback(IntPtr source, IntPtr engineCfg,
+                Rectangle faceLocation, EyeCondition eyeCondition, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void MvFaceFacialExpressionRecognizedCallback(IntPtr source,
+                IntPtr engineCfg, Rectangle faceLocation, FacialExpression facialExpression, IntPtr userData);
         }
 
         /// <summary>
@@ -70,34 +86,39 @@ internal static partial class Interop
         internal static partial class FaceRecognitionModel
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_create")]
-            internal static extern int Create(out IntPtr /* mv_face_recognition_model_h */ recognitionModel);
+            internal static extern MediaVisionError Create(out IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_destroy")]
-            internal static extern int Destroy(IntPtr /* mv_face_recognition_model_h */ recognitionModel);
+            internal static extern int Destroy(IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_clone")]
-            internal static extern int Clone(IntPtr /* mv_face_recognition_model_h */ src, out IntPtr /* mv_face_recognition_model_h */ dst);
+            internal static extern int Clone(IntPtr src, out IntPtr dst);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_save")]
-            internal static extern int Save(string fileName, IntPtr /* mv_face_recognition_model_h */ recognitionModel);
+            internal static extern MediaVisionError Save(string fileName, IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_load")]
-            internal static extern int Load(string fileName, out IntPtr /* mv_face_recognition_model_h */ recognitionModel);
+            internal static extern MediaVisionError Load(string fileName, out IntPtr handle);
+
+            [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_add")]
+            internal static extern MediaVisionError Add(IntPtr source, IntPtr recognitionModel,
+                ref Rectangle exampleLocation, int faceLabel);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_add")]
-            internal static extern int Add(IntPtr /* mv_source_h */ source, IntPtr /* mv_face_recognition_model_h */ recognitionModel, IntPtr exampleLocation, int faceLabel);
+            internal static extern MediaVisionError Add(IntPtr source, IntPtr recognitionModel,
+                IntPtr exampleLocation, int faceLabel);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_reset")]
-            internal static extern int Reset(IntPtr /* mv_face_recognition_model_h */ recognitionModel, IntPtr faceLabel);
+            internal static extern MediaVisionError Reset(IntPtr recognitionModel, IntPtr faceLabel = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_reset")]
-            internal static extern int Remove(IntPtr /* mv_face_recognition_model_h */ recognitionModel, ref int faceLabel);
+            internal static extern MediaVisionError Remove(IntPtr recognitionModel, ref int faceLabel);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_learn")]
-            internal static extern int Learn(IntPtr /* mv_engine_config_h */ engineCfg, IntPtr /* mv_face_recognition_model_h */ recognitionModel);
+            internal static extern MediaVisionError Learn(IntPtr engineCfg, IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_recognition_model_query_labels")]
-            internal static extern int QueryLabels(IntPtr /* mv_face_recognition_model_h */ recognitionModel, out IntPtr labels, out uint numberOfLabels);
+            internal static extern MediaVisionError QueryLabels(IntPtr handle, out IntPtr labels, out uint numberOfLabels);
         }
 
         /// <summary>
@@ -106,22 +127,27 @@ internal static partial class Interop
         internal static partial class FaceTrackingModel
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_tracking_model_create")]
-            internal static extern int Create(out IntPtr /* mv_face_tracking_model_h */ trackingModel);
+            internal static extern MediaVisionError Create(out IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_tracking_model_destroy")]
-            internal static extern int Destroy(IntPtr /* mv_face_tracking_model_h */ trackingModel);
+            internal static extern int Destroy(IntPtr handle);
+
+            [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_tracking_model_prepare")]
+            internal static extern MediaVisionError Prepare(IntPtr trackingModel, IntPtr engineCfg,
+                IntPtr source, ref Quadrangle location);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_tracking_model_prepare")]
-            internal static extern int Prepare(IntPtr /* mv_face_tracking_model_h */ trackingModel, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr /* mv_source_h */ source, IntPtr location);
+            internal static extern MediaVisionError Prepare(IntPtr trackingModel, IntPtr engineCfg,
+                IntPtr source, IntPtr location);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_tracking_model_clone")]
-            internal static extern int Clone(IntPtr /* mv_face_tracking_model_h */ src, out IntPtr /* mv_face_tracking_model_h */ dst);
+            internal static extern int Clone(IntPtr src, out IntPtr dst);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_tracking_model_save")]
-            internal static extern int Save(string fileName, IntPtr /* mv_face_tracking_model_h */ trackingModel);
+            internal static extern MediaVisionError Save(string fileName, IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_face_tracking_model_load")]
-            internal static extern int Load(string fileName, out IntPtr /* mv_face_tracking_model_h */ trackingModel);
+            internal static extern MediaVisionError Load(string fileName, out IntPtr handle);
         }
     }
 }
index 0aa9834..3afc9b5 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -16,6 +16,7 @@
 
 using System;
 using System.Runtime.InteropServices;
+using Tizen.Multimedia;
 
 /// <summary>
 /// Interop APIs
@@ -33,43 +34,51 @@ internal static partial class Interop
         internal static partial class Image
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_recognize")]
-            internal static extern int Recognize(IntPtr /* mv_source_h */ source, IntPtr /* mv_image_object_h */ imageObjects, int numberOfObjects, IntPtr /* mv_engine_config_h */ engineCfg, MvImageRecognizedCallback recognizedCb, IntPtr /* void */ userData);
+            internal static extern MediaVisionError Recognize(IntPtr source, IntPtr[] imageObjects,
+                int numberOfObjects, IntPtr engineCfg, RecognizedCallback recognizedCb, IntPtr userData = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_track")]
-            internal static extern int Track(IntPtr /* mv_source_h */ source, IntPtr /* mv_image_tracking_model_h */ imageTrackingModel, IntPtr /* mv_engine_config_h */ engineCfg, MvImageTrackedCallback trackedCb, IntPtr /* void */ userData);
+            internal static extern MediaVisionError Track(IntPtr source, IntPtr imageTrackingModel,
+                IntPtr engineCfg, TrackedCallback trackedCb, IntPtr userData = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_create")]
-            internal static extern int Create(out IntPtr /* mv_image_object_h */ imageObject);
+            internal static extern MediaVisionError Create(out IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_destroy")]
-            internal static extern int Destroy(IntPtr /* mv_image_object_h */ imageObject);
+            internal static extern int Destroy(IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_fill")]
-            internal static extern int Fill(IntPtr /* mv_image_object_h */ imageObject, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr /* mv_source_h */ source, IntPtr location);
+            internal static extern MediaVisionError Fill(IntPtr handle, IntPtr engineCfg, IntPtr source, ref Rectangle location);
+
+            [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_fill")]
+            internal static extern MediaVisionError Fill(IntPtr handle, IntPtr engineCfg, IntPtr source, IntPtr location);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_get_recognition_rate")]
-            internal static extern int GetRecognitionRate(IntPtr /* mv_image_object_h */ imageObject, out double recognitionRate);
+            internal static extern MediaVisionError GetRecognitionRate(IntPtr handle, out double recognitionRate);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_set_label")]
-            internal static extern int SetLabel(IntPtr /* mv_image_object_h */ imageObject, int label);
+            internal static extern MediaVisionError SetLabel(IntPtr handle, int label);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_get_label")]
-            internal static extern int GetLabel(IntPtr /* mv_image_object_h */ imageObject, out int label);
+            internal static extern MediaVisionError GetLabel(IntPtr handle, out int label);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_clone")]
-            internal static extern int Clone(IntPtr /* mv_image_object_h */ src, out IntPtr /* mv_image_object_h */ dst);
+            internal static extern int Clone(IntPtr src, out IntPtr dst);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_save")]
-            internal static extern int Save(string fileName, IntPtr /* mv_image_object_h */ imageObject);
+            internal static extern MediaVisionError Save(string fileName, IntPtr handle);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_object_load")]
-            internal static extern int Load(string fileName, out IntPtr /* mv_image_object_h */ imageObject);
+            internal static extern MediaVisionError Load(string fileName, out IntPtr handle);
 
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvImageRecognizedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr /* mv_image_object_h */ imageObjects, IntPtr locations, uint numberOfObjects, IntPtr /* void */ userData);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void RecognizedCallback(IntPtr source, IntPtr engineCfg, IntPtr imageObjects,
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)]
+                IntPtr[] locations, uint numberOfObjects, IntPtr userData);
 
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvImageTrackedCallback(IntPtr /* mv_source_h */ source, IntPtr /* mv_image_tracking_model_h */ imageTrackingModel, IntPtr /* mv_engine_config_h */ engineCfg, IntPtr location, IntPtr /* void */ userData);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void TrackedCallback(IntPtr source, IntPtr imageTrackingModel,
+                IntPtr engineCfg, IntPtr location, IntPtr  userData);
         }
 
         /// <summary>
@@ -78,25 +87,25 @@ internal static partial class Interop
         internal static partial class ImageTrackingModel
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_tracking_model_create")]
-            internal static extern int Create(out IntPtr /* mv_image_tracking_model_h */ imageTrackingModel);
+            internal static extern MediaVisionError Create(out IntPtr imageTrackingModel);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_tracking_model_set_target")]
-            internal static extern int SetTarget(IntPtr /* mv_image_object_h */ imageObject, IntPtr /* mv_image_tracking_model_h */ imageTrackingModel);
+            internal static extern MediaVisionError SetTarget(IntPtr handle, IntPtr imageTrackingModel);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_tracking_model_destroy")]
-            internal static extern int Destroy(IntPtr /* mv_image_tracking_model_h */ imageTrackingModel);
+            internal static extern int Destroy(IntPtr imageTrackingModel);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_tracking_model_refresh")]
-            internal static extern int Refresh(IntPtr /* mv_image_tracking_model_h */ imageTrackingModel, IntPtr /* mv_engine_config_h */ engineCfg);
+            internal static extern MediaVisionError Refresh(IntPtr imageTrackingModel, IntPtr engineCfg);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_tracking_model_clone")]
-            internal static extern int Clone(IntPtr /* mv_image_tracking_model_h */ src, out IntPtr /* mv_image_tracking_model_h */ dest);
+            internal static extern int Clone(IntPtr src, out IntPtr dest);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_tracking_model_save")]
-            internal static extern int Save(string fileName, IntPtr /* mv_image_tracking_model_h */ imageTrackingModel);
+            internal static extern MediaVisionError Save(string fileName, IntPtr imageTrackingModel);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_image_tracking_model_load")]
-            internal static extern int Load(string fileName, out IntPtr /* mv_image_tracking_model_h */ imageTrackingModel);
+            internal static extern MediaVisionError Load(string fileName, out IntPtr imageTrackingModel);
         }
     }
 }
index 6c0ac1e..22eb51b 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -16,6 +16,7 @@
 
 using System;
 using System.Runtime.InteropServices;
+using Tizen.Multimedia;
 
 /// <summary>
 /// Interop APIs
@@ -33,49 +34,58 @@ internal static partial class Interop
         internal static partial class Surveillance
         {
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_event_trigger_create")]
-            internal static extern int EventTriggerCreate(string eventType, out IntPtr /* mv_surveillance_event_trigger_h */ trigger);
+            internal static extern MediaVisionError EventTriggerCreate(string eventType, out IntPtr  trigger);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_event_trigger_destroy")]
-            internal static extern int EventTriggerDestroy(IntPtr /* mv_surveillance_event_trigger_h */ trigger);
+            internal static extern int EventTriggerDestroy(IntPtr  trigger);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_get_event_trigger_type")]
-            internal static extern int GetEventTriggerType(IntPtr /* mv_surveillance_event_trigger_h */ trigger, out string eventType);
+            internal static extern int GetEventTriggerType(IntPtr trigger, out string eventType);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_set_event_trigger_roi")]
-            internal static extern int SetEventTriggerRoi(IntPtr /* mv_surveillance_event_trigger_h */ trigger, int numberOfPoints, IntPtr roi);
+            internal static extern MediaVisionError SetEventTriggerRoi(IntPtr trigger, int numberOfPoints, Point[] roi);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_get_event_trigger_roi")]
-            internal static extern int GetEventTriggerRoi(IntPtr /* mv_surveillance_event_trigger_h */ trigger, out int numberOfPoints, out IntPtr roi);
+            internal static extern MediaVisionError GetEventTriggerRoi(IntPtr trigger, out int numberOfPoints, out IntPtr roi);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_subscribe_event_trigger")]
-            internal static extern int SubscribeEventTrigger(IntPtr /* mv_surveillance_event_trigger_h */ trigger, int videoStreamId, IntPtr /* mv_engine_config_h */ engineCfg, MvSurveillanceEventOccurredCallback callback, IntPtr /* void */ userData);
+            internal static extern MediaVisionError SubscribeEventTrigger(IntPtr trigger, int videoStreamId,
+                IntPtr engineCfg, EventOccurredCallback callback, IntPtr userData = default(IntPtr));
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_unsubscribe_event_trigger")]
-            internal static extern int UnsubscribeEventTrigger(IntPtr /* mv_surveillance_event_trigger_h */ trigger, int videoStreamId);
+            internal static extern MediaVisionError UnsubscribeEventTrigger(IntPtr trigger, int videoStreamId);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_push_source")]
-            internal static extern int PushSource(IntPtr /* mv_source_h */ source, int videoStreamId);
+            internal static extern MediaVisionError PushSource(IntPtr source, int videoStreamId);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_foreach_supported_event_type")]
-            internal static extern int ForeachSupportedEventType(MvSurveillanceEventTypeCallback callback, IntPtr /* void */ userData);
+            internal static extern int ForeachSupportedEventType(EventTypeCallback callback, IntPtr userData);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_foreach_event_result_name")]
-            internal static extern int ForeachEventResultName(string eventType, MvSurveillanceEventResultNameCallback callback, IntPtr /* void */ userData);
+            internal static extern int ForeachEventResultName(string eventType, EventResultNameCallback callback,
+                IntPtr userData);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_get_result_value")]
-            internal static extern int GetResultCount(IntPtr /* mv_surveillance_result_h */ result, string name, out int /* void */ value);
+            internal static extern MediaVisionError GetResultValue(IntPtr result, string name, out int value);
 
             [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_get_result_value")]
-            internal static extern int GetResultValue(IntPtr /* mv_surveillance_result_h */ result, string name, IntPtr /* void */ value);
+            internal static extern MediaVisionError GetResultValue(IntPtr result, string name, [Out] int[] value);
 
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate void MvSurveillanceEventOccurredCallback(IntPtr /* mv_surveillance_event_trigger_h */ trigger, IntPtr /* mv_source_h */ source, int videoStreamId, IntPtr /* mv_surveillance_result_h */ eventResult, IntPtr /* void */ userData);
+            [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_get_result_value")]
+            internal static extern MediaVisionError GetResultValue(IntPtr result, string name, [Out] double[] value);
+
+            [DllImport(Libraries.MediaVision, EntryPoint = "mv_surveillance_get_result_value")]
+            internal static extern MediaVisionError GetResultValue(IntPtr result, string name, [Out] Rectangle[] value);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate void EventOccurredCallback(IntPtr trigger, IntPtr source,
+                int videoStreamId, IntPtr eventResult, IntPtr userData);
 
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate bool MvSurveillanceEventTypeCallback(string eventType, IntPtr /* void */ userData);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate bool EventTypeCallback(string eventType, IntPtr userData);
 
-            [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
-            internal delegate bool MvSurveillanceEventResultNameCallback(string name, IntPtr /* void */ userData);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            internal delegate bool EventResultNameCallback(string name, IntPtr userData);
         }
     }
 }
index 1fc5c25..87f9fc3 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents a detected barcode.
+    /// Represents a detected barcode.
     /// </summary>
     public class Barcode
     {
-        internal Barcode()
+        public Barcode(Quadrangle location, string message, BarcodeType type)
         {
+            Region = location;
+            Message = message;
+            Type = type;
         }
 
         /// <summary>
-        /// The quadrangle location of detected barcode
+        /// The quadrangle location of detected barcode.
         /// </summary>
-        public Quadrangle Location { get; internal set; }
+        public Quadrangle Region { get; }
 
         /// <summary>
-        /// The decoded message of barcode
+        /// The decoded message of barcode.
         /// </summary>
-        public string Message { get; internal set; }
+        public string Message { get; }
 
         /// <summary>
-        /// The type of detected barcode
+        /// The type of detected barcode.
         /// </summary>
-        public BarcodeType Type { get; internal set; }
+        public BarcodeType Type { get; }
+
+        public override string ToString() =>
+            $"Region={Region}, Message={Message}, Type={Type.ToString()}";
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/BarcodeDetectionConfiguration.cs b/src/Tizen.Multimedia/MediaVision/BarcodeDetectionConfiguration.cs
new file mode 100644 (file)
index 0000000..a02bcc5
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="BarcodeDetector"/>.
+    /// </summary>
+    /// <seealso cref="BarcodeDetector"/>
+    public class BarcodeDetectionConfiguration : EngineConfiguration
+    {
+        private const string KeyAttrTarget = "MV_BARCODE_DETECT_ATTR_TARGET";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BarcodeDetectionConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="System.NotSupportedException">The feature is not supported.</exception>
+        public BarcodeDetectionConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the target of the barcode detection.
+        /// </summary>
+        /// <exception cref="System.ArgumentException"><paramref name="value"/> is not valid.</exception>
+        /// <exception cref="System.ObjectDisposedException">The <see cref="BarcodeDetectionConfiguration"/> already has been disposed of.</exception>
+        public BarcodeDetectionTarget Target
+        {
+            get
+            {
+                return (BarcodeDetectionTarget)GetInt(KeyAttrTarget);
+            }
+            set
+            {
+                ValidationUtil.ValidateEnum(typeof(BarcodeDetectionTarget), value);
+                Set(KeyAttrTarget, (int)value);
+            }
+        }
+    }
+}
old mode 100755 (executable)
new mode 100644 (file)
similarity index 85%
rename from src/Tizen.Multimedia/MediaVision/TargetAttribute.cs
rename to src/Tizen.Multimedia/MediaVision/BarcodeDetectionTarget.cs
index 6a36780..3de3b18
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration to target attribute
+    /// Specifies the target of <see cref="BarcodeDetector"/>.
     /// </summary>
-    public enum TargetAttribute
+    public enum BarcodeDetectionTarget
     {
         /// <summary>
         /// 1D and 2D
         /// </summary>
         All,
+
         /// <summary>
         /// 1D barcode only
         /// </summary>
         Barcode1D,
+
         /// <summary>
         /// 2D barcode only
         /// </summary>
         Barcode2D,
-        /// <summary>
-        /// Unavailable
-        /// </summary>
-        Unavailable
     }
 }
index 113cd3c..8430537 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 
 using System;
 using System.Collections.Generic;
-using System.Runtime.InteropServices;
 using System.Threading.Tasks;
-using static Interop.MediaVision;
+using InteropBarcode = Interop.MediaVision.BarcodeDetector;
+using Unmanaged = Interop.MediaVision;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class contains the Media Vision barcode detect API.\n
-    /// These APIs can be used for detecting barcodes on image sources, reading encoded messages, getting barcode types.
+    /// Provides the ability to detect barcodes on image sources.
     /// </summary>
     public static class BarcodeDetector
     {
         /// <summary>
-        /// Detects barcode(s) on source and reads message from it.
+        /// Detects barcodes on source and reads message from it.
         /// </summary>
-        /// <param name="source">The media vision source object</param>
-        /// <param name="config">The configuration of the barcode detector engine </param>
-        /// <param name="roi">Region of interest - rectangular area on the source which will be used for barcode detection Note that roi should be inside area on the source.</param>
-        /// <returns>Returns list of barcode detected asynchronously</returns>
-        /// <code>
-        ///
-        /// </code>
-        public static async Task<List<Barcode>> DetectAsync(MediaVisionSource source, BarcodeDetectorEngineConfiguration config, Rectangle roi)
+        /// <param name="source">The <see cref="MediaVisionSource"/> instance.</param>
+        /// <param name="roi">Region of interest - rectangular area on the source which will be used for
+        ///     barcode detection. Note that roi should be inside area on the source.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="source"/> already has been disposed of.</exception>
+        /// <returns>A task that represents the asynchronous detect operation.</returns>
+        /// <seealso cref="Barcode"/>
+        public static async Task<IEnumerable<Barcode>> DetectAsync(MediaVisionSource source,
+            Rectangle roi)
         {
-            TaskCompletionSource<List<Barcode>> tcsBarcodeList = new TaskCompletionSource<List<Barcode>>();
-            Interop.MediaVision.Rectangle rectangle = new Interop.MediaVision.Rectangle()
+            return await DetectAsync(source, roi, null);
+        }
+
+        /// <summary>
+        /// Detects barcodes on source and reads message from it with <see cref="BarcodeDetectionConfiguration"/>.
+        /// </summary>
+        /// <param name="source">The <see cref="MediaVisionSource"/> instance.</param>
+        /// <param name="roi">Region of interest - rectangular area on the source which will be used for
+        ///     barcode detection. Note that roi should be inside area on the source.</param>
+        /// <param name="config">The configuration of the barcode detector. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous detect operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> already has been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> already has been disposed of.
+        /// </exception>
+        /// <seealso cref="Barcode"/>
+        public static async Task<IEnumerable<Barcode>> DetectAsync(MediaVisionSource source,
+            Rectangle roi, BarcodeDetectionConfiguration config)
+        {
+            if (source == null)
             {
-                x = roi.Point.X,
-                y = roi.Point.Y,
-                width = roi.Width,
-                height = roi.Height
-            };
+                throw new ArgumentNullException(nameof(source));
+            }
 
-            // Define native callback
-            Interop.MediaVision.BarCodeDetector.MvBarcodeDetectedCallback detectedCb = (IntPtr mvSource, IntPtr engineCfg, IntPtr barcodeLocations, IntPtr messages, IntPtr types, int numberOfBarcodes, IntPtr userData) =>
+            var tcs = new TaskCompletionSource<IEnumerable<Barcode>>();
+
+            using (var cb = ObjectKeeper.Get(GetCallback(tcs)))
             {
-                try
-                {
-                    Log.Info(MediaVisionLog.Tag, String.Format("Barcodes detected, count : {0}", numberOfBarcodes));
-                    List<Barcode> barcodes = new List<Barcode>();
-                    if (numberOfBarcodes > 0)
-                    {
-                        IntPtr[] msgPtr = new IntPtr[numberOfBarcodes];
-                        Marshal.Copy(messages, msgPtr, 0, numberOfBarcodes);
+                InteropBarcode.Detect(source.Handle, EngineConfiguration.GetHandle(config),
+                    roi.ToMarshalable(), cb.Target).Validate("Failed to detect barcode.");
+
+                return await tcs.Task;
+            }
+        }
 
-                        // Prepare list of barcodes
-                        for (int i = 0; i < numberOfBarcodes; i++)
-                        {
-                            Interop.MediaVision.Quadrangle location = (Interop.MediaVision.Quadrangle)Marshal.PtrToStructure(barcodeLocations, typeof(Interop.MediaVision.Quadrangle));
-                            string message = Marshal.PtrToStringAnsi(msgPtr[i]);
-                            BarcodeType type = (BarcodeType)Marshal.ReadInt32(types);
-                            Quadrangle quadrangle = new Quadrangle()
-                            {
-                                Points = new Point[4]
-                                {
-                                    new Point(location.x1, location.y1),
-                                    new Point(location.x2, location.y2),
-                                    new Point(location.x3, location.y3),
-                                    new Point(location.x4, location.y4)
-                                }
-                            };
-                            Log.Info(MediaVisionLog.Tag, String.Format("Location : {0}, Message : {1}, Type : {2}", quadrangle.ToString(), message, type));
-                            Barcode barcode = new Barcode()
-                            {
-                                Location = quadrangle,
-                                Message = message,
-                                Type = type
-                            };
-                            barcodes.Add(barcode);
-                            barcodeLocations = IntPtr.Add(barcodeLocations, sizeof(int) * 8);
-                            types = IntPtr.Add(barcodeLocations, sizeof(BarcodeType));
-                        }
-                    }
+        private static Barcode[] CreateBarcodes(Unmanaged.Quadrangle[] locations, string[] messages,
+            BarcodeType[] types, int numberOfBarcodes)
+        {
+            Barcode[] barcodes = new Barcode[numberOfBarcodes];
+
+            for (int i = 0; i < numberOfBarcodes; i++)
+            {
+                barcodes[i] = new Barcode(locations[i].ToApiStruct(), messages[i], types[i]);
+
+                Log.Info(MediaVisionLog.Tag, barcodes[i].ToString());
+            }
+
+            return barcodes;
+        }
 
-                    if (!tcsBarcodeList.TrySetResult(barcodes))
-                    {
-                        Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                        tcsBarcodeList.TrySetException(new InvalidOperationException("Failed to set result"));
-                    }
+        private static InteropBarcode.DetectedCallback GetCallback(TaskCompletionSource<IEnumerable<Barcode>> tcs)
+        {
+            return (IntPtr mvSource, IntPtr engineCfg, Unmanaged.Quadrangle[] locations, string[] messages,
+                BarcodeType[] types, int numberOfBarcodes, IntPtr userData) =>
+            {
+                Log.Info(MediaVisionLog.Tag, $"Barcodes detected, count : {numberOfBarcodes}");
+
+                try
+                {
+                    tcs.TrySetResult(CreateBarcodes(locations, messages, types, numberOfBarcodes));
                 }
-                catch (Exception ex)
+                catch (Exception e)
                 {
-                    Log.Info(MediaVisionLog.Tag, "exception :" + ex.ToString());
-                    tcsBarcodeList.TrySetException(ex);
+                    MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle barcode detection callback", e);
+                    tcs.TrySetException(e);
                 }
             };
-            int ret = Interop.MediaVision.BarCodeDetector.Detect(source._sourceHandle, config._engineHandle, rectangle, detectedCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to detect barcode.");
-            return await tcsBarcodeList.Task;
         }
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/BarcodeDetectorEngineConfiguration.cs b/src/Tizen.Multimedia/MediaVision/BarcodeDetectorEngineConfiguration.cs
deleted file mode 100755 (executable)
index 2c54e76..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents concrete EngineConfig for BarcodeDetector
-    /// </summary>
-    public class BarcodeDetectorEngineConfiguration : EngineConfiguration
-    {
-        private const string _targetAttributeKey = "MV_BARCODE_DETECT_ATTR_TARGET";
-        private TargetAttribute _targetAttr = TargetAttribute.All;
-
-        /// <summary>
-        /// The default constructor of BarcodeDetectorEngineConfig class
-        /// </summary>
-        /// <code>
-        /// 
-        /// </code>
-        public BarcodeDetectorEngineConfiguration()
-            : base()
-        {
-            TargetAttribute = _targetAttr;
-        }
-
-        /// <summary>
-        /// Sets and gets target attribute of the engine configuration
-        /// </summary>
-        public TargetAttribute TargetAttribute
-        {
-            get
-            {
-                return _targetAttr;
-            }
-
-            set
-            {
-                if (!IsValid(value))
-                {
-                    throw new ArgumentException("TargetAttribute value is invalid");
-                }
-
-                Add<int>(_targetAttributeKey, (int)value);
-                _targetAttr = value;
-            }
-        }
-
-        private bool IsValid(TargetAttribute value)
-        {
-            if (value == TargetAttribute.Unavailable)
-            {
-                Log.Error(MediaVisionLog.Tag, "Invalid TargetAttribute");
-                return false;
-            }
-
-            return true;
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/BarcodeGenerationConfiguration.cs b/src/Tizen.Multimedia/MediaVision/BarcodeGenerationConfiguration.cs
new file mode 100644 (file)
index 0000000..88d2cfe
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using Tizen.Common;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="BarcodeGenerator"/> instances.
+    /// </summary>
+    /// <seealso cref="BarcodeGenerator"/>
+    public class BarcodeGenerationConfiguration : EngineConfiguration
+    {
+        private const string KeyTextAttr = "MV_BARCODE_GENERATE_ATTR_TEXT";
+        private const string KeyForegroundColorAttr = "MV_BARCODE_GENERATE_ATTR_COLOR_FRONT";
+        private const string KeyBackgroundColorAttr = "MV_BARCODE_GENERATE_ATTR_COLOR_BACK";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BarcodeGenerationConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="System.NotSupportedException">The feature is not supported.</exception>
+        public BarcodeGenerationConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the text visibility of the barcode to be generated.
+        /// </summary>
+        /// <exception cref="System.ArgumentException"><paramref name="value"/> is not valid.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="BarcodeGenerationConfiguration"/> already has been disposed of.</exception>
+        public Visibility TextVisibility
+        {
+            get
+            {
+                return (Visibility)GetInt(KeyTextAttr);
+            }
+            set
+            {
+                ValidationUtil.ValidateEnum(typeof(Visibility), value);
+                Set(KeyTextAttr, (int)value);
+            }
+        }
+
+        private Color _foregroundColor = Color.Black;
+
+        /// <summary>
+        /// Sets or gets the foreground color of the barcode to be generated.
+        /// </summary>
+        /// <remarks>
+        /// The alpha value of the color will be ignored.
+        /// </remarks>
+        /// <exception cref="ObjectDisposedException">The <see cref="BarcodeGenerationConfiguration"/> already has been disposed of.</exception>
+        public Color ForegroundColor
+        {
+            get
+            {
+                return _foregroundColor;
+            }
+            set
+            {
+                Set(KeyForegroundColorAttr, string.Format("{0:x2}{1:x2}{2:x2}", value.R, value.G, value.B));
+                _foregroundColor = value;
+            }
+        }
+
+        private Color _backgroundColor = Color.White;
+
+        /// <summary>
+        /// Sets or gets the background color of the barcode to be generated.
+        /// </summary>
+        /// <remarks>
+        /// The alpha value of the color will be ignored.
+        /// </remarks>
+        /// <exception cref="ObjectDisposedException">The <see cref="BarcodeGenerationConfiguration"/> already has been disposed of.</exception>
+        public Color BackgroundColor
+        {
+            get
+            {
+                return _backgroundColor;
+            }
+            set
+            {
+                Set(KeyBackgroundColorAttr, string.Format("{0:x2}{1:x2}{2:x2}", value.R, value.G, value.B));
+                _backgroundColor = value;
+            }
+        }
+    }
+}
index 3ec2c38..160b51c 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  */
 
 using System;
+using InteropBarcode = Interop.MediaVision.BarcodeGenerator;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class contains the Media Vision barcode generate API.\n
-    /// These APIs can be used for generating the barcodes and QR codes.
-    /// Different encoding types <see cref="QrMode"/> , error correction codes <see cref="ErrorCorrectionLevel"/>  and code versions are supported for QRCodes.
+    /// Provides the ability to generate barcodes and QR codes.
+    /// Different encoding types <see cref="QrMode"/> , error correction codes <see cref="ErrorCorrectionLevel"/>
+    /// and code versions are supported for QRCodes.
     /// </summary>
+    /// <seealso cref="BarcodeGenerationConfiguration"/>
     public static class BarcodeGenerator
     {
+        private const int NoneErrorCorrection = (int)ErrorCorrectionLevel.High + 1;
+        private const int NoneQrMode = (int)QrMode.Utf8 + 1;
+
+        private static MediaVisionSource GenerateSource(BarcodeGenerationConfiguration config,
+            string message, BarcodeType type, int qrMode, int qrEcc, int qrVersion)
+        {
+            if (message == null)
+            {
+                throw new ArgumentNullException(nameof(message));
+            }
+
+            ValidationUtil.ValidateEnum(typeof(BarcodeType), type);
+
+            MediaVisionSource source = new MediaVisionSource();
+            try
+            {
+                InteropBarcode.GenerateSource(EngineConfiguration.GetHandle(config),
+                    message, type, qrMode, qrEcc, qrVersion, source.Handle).
+                    Validate("Failed to generate source");
+            }
+            catch (Exception)
+            {
+                source.Dispose();
+                throw;
+            }
+            return source;
+        }
+
         /// <summary>
-        /// Generates <see cref="MediaVisionSource"/> with barcode image.
+        /// Generates a QR image with the specified message.
         /// </summary>
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param>
+        /// <returns><see cref="MediaVisionSource"/> containing the generated QR image.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="qrConfig"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="message"/> is null.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>.
+        ///     </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <seealso cref="QrMode"/>
+        public static MediaVisionSource GenerateSource(string message, QrConfiguration qrConfig)
+        {
+            return GenerateSource(message, qrConfig, null);
+        }
+
+        /// <summary>
+        /// Generates a QR image with the specified message with <see cref="BarcodeGenerationConfiguration"/>.
+        /// </summary>
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param>
+        /// <param name="config">The configuration of the barcode generator. This value can be null.</param>
+        /// <returns><see cref="MediaVisionSource"/> containing the generated QR image.</returns>
         /// <remarks>
-        /// If the text attribute of engine configuration is set to <see cref="TextAttribute.Visible"/> , InvalidOperationException will be thrown when type is <see cref="BarcodeType.QR"/>
+        ///     <see cref="BarcodeGenerationConfiguration.TextVisibility"/> must be <see cref="Visibility.Invisible"/>,
+        ///     because the text visibility is not supported in the QR code.
         /// </remarks>
-        /// <param name="config">The configuration of the bar code generator engine</param>
-        /// <param name="message">The message to be encoded in the barcode</param>
-        /// <param name="type">Type of the barcode to be generated</param>
-        /// <param name="qrConfig">The QrConfig object - required for QR codes only</param>
-        /// <returns>
-        /// <param name="source">The media vision source object which will be used to fill by the buffer with generated image</param>
-        /// </returns>
-        /// <code>
-        /// 
-        /// </code>
-        public static MediaVisionSource GenerateSource(BarcodeGeneratorEngineConfiguration config, string message, BarcodeType type, QrConfiguration qrConfig = null)
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="qrConfig"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="message"/> is null.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>.
+        /// </exception>
+        /// <exception cref="NotSupportedException">
+        ///     The feature is not supported.\n
+        ///     - or -\n
+        ///     <see cref="BarcodeGenerationConfiguration.TextVisibility"/> is the <see cref="Visibility.Visible"/>.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception>
+        /// <seealso cref="QrMode"/>
+        public static MediaVisionSource GenerateSource(string message, QrConfiguration qrConfig,
+            BarcodeGenerationConfiguration config)
         {
-            if (string.IsNullOrEmpty(message) ||
-                type == BarcodeType.Undefined ||
-                (type == BarcodeType.QR &&
-                (qrConfig == null ||
-                qrConfig.ErrorCorrectionLevel == ErrorCorrectionLevel.Unavailable ||
-                qrConfig.Mode == QrMode.Unavailable ||
-                qrConfig.Version < 1 ||
-                qrConfig.Version > 40)))
+            if (qrConfig == null)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new ArgumentNullException(nameof(qrConfig));
             }
 
-            MediaVisionSource source = new MediaVisionSource();
-            int ret = (type == BarcodeType.QR) ?
-                        Interop.MediaVision.BarCodeGenerator.GenerateSource(config._engineHandle, message, type, qrConfig.Mode, qrConfig.ErrorCorrectionLevel, qrConfig.Version, source._sourceHandle) :
-                        Interop.MediaVision.BarCodeGenerator.GenerateSource(config._engineHandle, message, type, QrMode.Unavailable, ErrorCorrectionLevel.Unavailable, 0, source._sourceHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to generate source");
-            return source;
+            if (config != null)
+            {
+                if (config.TextVisibility == Visibility.Visible)
+                {
+                    throw new NotSupportedException("Text can't be visible in QR.");
+                }
+            }
+
+            return GenerateSource(config, message, BarcodeType.QR, (int)qrConfig.Mode,
+                (int)qrConfig.ErrorCorrectionLevel, qrConfig.Version);
         }
 
         /// <summary>
-        /// Generates image file with barcode.
+        /// Generates a barcode image with the specified message.
+        /// </summary>
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="type">Type of the barcode to be generated.</param>
+        /// <returns><see cref="MediaVisionSource"/> containing the generated barcode image.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="type"/> is <see cref="BarcodeType.QR"/>.\n
+        ///     - or -\n
+        ///     <paramref name="type"/> is invalid.
+        ///     - or -\n
+        ///     <paramref name="message"/> contains illegal characters.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public static MediaVisionSource GenerateSource(string message, BarcodeType type)
+        {
+            return GenerateSource(message, type, null);
+        }
+
+        /// <summary>
+        /// Generates a barcode image with the specified message and <see cref="BarcodeGenerationConfiguration"/>.
+        /// </summary>
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="type">Type of the barcode to be generated.</param>
+        /// <param name="config">The configuration of the barcode generator. This value can be null.</param>
+        /// <returns><see cref="MediaVisionSource"/> containing the generated barcode image.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="type"/> is <see cref="BarcodeType.QR"/>.
+        ///     - or -\n
+        ///     <paramref name="type"/> is invalid.
+        ///     - or -\n
+        ///     <paramref name="message"/> contains illegal characters.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception>
+        public static MediaVisionSource GenerateSource(string message, BarcodeType type,
+            BarcodeGenerationConfiguration config)
+        {
+            if (type == BarcodeType.QR)
+            {
+                throw new ArgumentException($"Invalid barcode type : {type}.");
+            }
+
+            return GenerateSource(config, message, type, NoneQrMode, NoneErrorCorrection, 0);
+        }
+
+        private static void GenerateImage(BarcodeGenerationConfiguration config,
+            string message, BarcodeType type, BarcodeImageConfiguration imageConfig,
+            int qrMode, int qrEcc, int qrVersion)
+        {
+            if (message == null)
+            {
+                throw new ArgumentNullException(nameof(message));
+            }
+
+            if (imageConfig == null)
+            {
+                throw new ArgumentNullException(nameof(imageConfig));
+            }
+
+            ValidationUtil.ValidateEnum(typeof(BarcodeType), type);
+
+            InteropBarcode.GenerateImage(EngineConfiguration.GetHandle(config), message,
+                imageConfig.Width, imageConfig.Height, type, qrMode, qrEcc, qrVersion,
+                imageConfig.Path, imageConfig.Format).
+                Validate("Failed to generate image");
+        }
+
+        /// <summary>
+        /// Generates a QR image file with the specified message.
+        /// </summary>
+        /// <remarks>
+        ///     <see cref="BarcodeGenerationConfiguration.TextVisibility"/> must be <see cref="Visibility.Invisible"/>,
+        ///     because the text visibility is not supported in the QR code.
+        /// </remarks>
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param>
+        /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains information about the file to be generated.</param>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="messsage"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="qrConfig"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageConfig"/> is null.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <seealso cref="QrMode"/>
+        public static void GenerateImage(string message, QrConfiguration qrConfig,
+            BarcodeImageConfiguration imageConfig)
+        {
+            GenerateImage(message, qrConfig, imageConfig, null);
+        }
+
+        /// <summary>
+        /// Generates a QR image file with the specified message and <see cref="BarcodeGenerationConfiguration"/>.
         /// </summary>
         /// <remarks>
-        /// If the text attribute of engine configuration is set to <see cref="TextAttribute.Visible"/> ,
-        /// InvalidOperationException will be thrown when type is <see cref="BarcodeType.QR"/>\n
+        ///     <see cref="BarcodeGenerationConfiguration.TextVisibility"/> must be <see cref="Visibility.Invisible"/>,
+        ///     because the text visibility is not supported in the QR code.
         /// </remarks>
-        /// <param name="config">The configuration of the bar code generator engine</param>
-        /// <param name="message">The message to be encoded in the barcode</param>
-        /// <param name="type">Type of the barcode to be generated</param>
-        /// <param name="imageConfig">The BarcodeImageConfig object that contains information about the file to be generated</param>
-        /// <param name="qrConfig">The QrConfig object - required for QR codes only</param>
-        /// <code>
-        /// 
-        /// </code>
-        public static void GenerateImage(BarcodeGeneratorEngineConfiguration config, string message, BarcodeType type, BarcodeImageConfiguration imageConfig, QrConfiguration qrConfig = null)
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param>
+        /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains
+        ///     information about the file to be generated.</param>
+        /// <param name="config">The configuration of the barcode generator. This value can be null.</param>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="messsage"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="qrConfig"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageConfig"/> is null.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     The feature is not supported.\n
+        ///     - or -\n
+        ///     <see cref="BarcodeGenerationConfiguration.TextVisibility"/> is the <see cref="Visibility.Visible"/>.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception>
+        public static void GenerateImage(string message, QrConfiguration qrConfig,
+            BarcodeImageConfiguration imageConfig, BarcodeGenerationConfiguration config)
         {
-            if (string.IsNullOrEmpty(message) ||
-                imageConfig == null ||
-                string.IsNullOrEmpty(imageConfig.Path) ||
-                type == BarcodeType.Undefined ||
-                (type == BarcodeType.QR &&
-                (qrConfig == null ||
-                qrConfig.ErrorCorrectionLevel == ErrorCorrectionLevel.Unavailable ||
-                qrConfig.Mode == QrMode.Unavailable ||
-                qrConfig.Version < 1 ||
-                qrConfig.Version > 40)))
+            if (qrConfig == null)
+            {
+                throw new ArgumentNullException(nameof(qrConfig));
+            }
+
+            if (config.TextVisibility == Visibility.Visible)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new NotSupportedException("Text can't be visible in QR.");
             }
 
-            int ret = (type == BarcodeType.QR) ?
-                        Interop.MediaVision.BarCodeGenerator.GenerateImage(config._engineHandle,
-                                                                            message,
-                                                                            imageConfig.Width,
-                                                                            imageConfig.Height,
-                                                                            type,
-                                                                            qrConfig.Mode,
-                                                                            qrConfig.ErrorCorrectionLevel,
-                                                                            qrConfig.Version,
-                                                                            imageConfig.Path,
-                                                                            imageConfig.Format) :
-                        Interop.MediaVision.BarCodeGenerator.GenerateImage(config._engineHandle,
-                                                                            message,
-                                                                            imageConfig.Width,
-                                                                            imageConfig.Height,
-                                                                            type,
-                                                                            QrMode.Unavailable,
-                                                                            ErrorCorrectionLevel.Unavailable,
-                                                                            0,
-                                                                            imageConfig.Path,
-                                                                            imageConfig.Format);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to generate image");
+            GenerateImage(config, message, BarcodeType.QR, imageConfig, (int)qrConfig.Mode,
+                (int)qrConfig.ErrorCorrectionLevel, qrConfig.Version);
+        }
+
+        /// <summary>
+        /// Generates a barcode image file with the specified message.
+        /// </summary>
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="type">Type of the barcode to be generated.</param>
+        /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains
+        ///     information about the file to be generated.</param>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="messsage"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageConfig"/> is null.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="type"/> is <see cref="BarcodeType.QR"/>.
+        ///     - or -\n
+        ///     <paramref name="type"/> is invalid.
+        ///     - or -\n
+        ///     <paramref name="message"/> contains illegal characters.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public static void GenerateImage(string message, BarcodeType type, BarcodeImageConfiguration imageConfig)
+        {
+            GenerateImage(message, type, imageConfig, null);
+        }
+
+        /// <summary>
+        /// Generates a barcode image file with the specified message and <see cref="BarcodeGenerationConfiguration"/>.
+        /// </summary>
+        /// <param name="message">The message to be encoded in the barcode.</param>
+        /// <param name="type">Type of the barcode to be generated.</param>
+        /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains
+        ///     information about the file to be generated.</param>
+        /// <param name="config">The configuration of the barcode generator. This value can be null.</param>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="messsage"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageConfig"/> is null.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="message"/> is too long.\n
+        ///     - or -\n
+        ///     <paramref name="type"/> is <see cref="BarcodeType.QR"/>.
+        ///     - or -\n
+        ///     <paramref name="type"/> is invalid.
+        ///     - or -\n
+        ///     <paramref name="message"/> contains illegal characters.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception>
+        public static void GenerateImage(string message,
+            BarcodeType type, BarcodeImageConfiguration imageConfig, BarcodeGenerationConfiguration config)
+        {
+            if (type == BarcodeType.QR)
+            {
+                throw new ArgumentException($"Invalid barcode type : {type}.");
+            }
+            GenerateImage(config, message, type, imageConfig, NoneQrMode, NoneErrorCorrection, 0);
         }
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/BarcodeGeneratorEngineConfiguration.cs b/src/Tizen.Multimedia/MediaVision/BarcodeGeneratorEngineConfiguration.cs
deleted file mode 100755 (executable)
index b90c645..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents concrete EngineConfig for BarcodeGenerator
-    /// </summary>
-    public class BarcodeGeneratorEngineConfiguration : EngineConfiguration
-    {
-        private const string _textAttributeKey = "MV_BARCODE_GENERATE_ATTR_TEXT";
-        private const string _frontColorAttributeKey = "MV_BARCODE_GENERATE_ATTR_COLOR_FRONT";
-        private const string _backColorAttributeKey = "MV_BARCODE_GENERATE_ATTR_COLOR_BACK";
-        private TextAttribute _textAttr = TextAttribute.Invisible;
-        private string _frontColor = "000000";
-        private string _backColor = "ffffff";
-
-        /// <summary>
-        /// The default constructor of BarcodeGeneratorEngineConfig class
-        /// </summary>
-        /// <code>
-        /// 
-        /// </code>
-        public BarcodeGeneratorEngineConfiguration()
-            : base()
-        {
-            TextAttribute = _textAttr;
-            FrontColor = _frontColor;
-            BackColor = _backColor;
-        }
-
-        /// <summary>
-        /// Sets and gets text attribute of the engine configuration
-        /// </summary>
-        public TextAttribute TextAttribute
-        {
-            get
-            {
-                return _textAttr;
-            }
-
-            set
-            {
-                if (!IsValid(value))
-                {
-                    throw new ArgumentException("TextAttribute value is invalid");
-                }
-
-                Add<int>(_textAttributeKey, (int)value);
-                _textAttr = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets barcode's foreground color attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// This attribute represents RGB color as a hex triplet with six digits.
-        /// </remarks>
-        public string FrontColor
-        {
-            get
-            {
-                return _frontColor;
-            }
-
-            set
-            {
-                Add<string>(_frontColorAttributeKey, value);
-                _frontColor = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets barcode's background color attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// This property represents RGB color as a hex triplet with six digits.
-        /// </remarks>
-        public string BackColor
-        {
-            get
-            {
-                return _backColor;
-            }
-
-            set
-            {
-                Add<string>(_backColorAttributeKey, value);
-                _backColor = value;
-            }
-        }
-
-        private bool IsValid(TextAttribute value)
-        {
-            if (value == TextAttribute.Unavailable)
-            {
-                Log.Error(MediaVisionLog.Tag, "Invalid TextAttribute");
-                return false;
-            }
-
-            return true;
-        }
-    }
-}
index 2dc288c..be055ee 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  * limitations under the License.
  */
 
+using System;
+
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents the configuration details for the barcode image file to be generated by BarcodeGenerator
+    /// Represents a configuration for the image to be generated by <see cref="BarcodeGenerator"/>.
     /// </summary>
     public class BarcodeImageConfiguration
     {
         /// <summary>
-        /// The constructor of the BarcodeImageConfig class
+        /// Initializes a new instance of the <see cref="BarcodeImageConfiguration"/> class.
         /// </summary>
         /// <remarks>
-        /// The mediastorage privilege http://tizen.org/privilege/mediastorage is needed if image path is relevant to media storage.\n
-        /// The externalstorage privilege http://tizen.org/privilege/externalstorage is needed if image path is relevant to external storage.
+        /// The mediastorage privilege(http://tizen.org/privilege/mediastorage) is needed if image path is relevant to media storage.\n
+        /// The externalstorage privilege(http://tizen.org/privilege/externalstorage) is needed if image path is relevant to external storage.
         /// </remarks>
-        /// <param name="width">The width of the generated image</param>
-        /// <param name="height">The height of the generated image</param>
-        /// <param name="path">The path to the file that has to be generated</param>
-        /// <param name="imageFormat">The format of the output image</param>
+        /// <param name="size">The <see cref="Size"/> of the generated image.</param>
+        /// <param name="path">The path to the file to be generated.</param>
+        /// <param name="imageFormat">The format of the output image.</param>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     The width of <paramref name="size"/> is less than or equal to zero.\n
+        ///     - or -\n
+        ///     The height of <paramref name="size"/> is less than or equal to zero.
+        /// </exception>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="ArgumentException"><paramref name="imageFormat"/> is invalid.</exception>
         /// <code>
-        /// BarcodeImageConfiguration imageConfig = new BarcodeImageConfiguration(500, 400, "/opt/usr/test-barcode-generate-new", BarcodeImageFormat.JPG);
+        /// BarcodeImageConfiguration imageConfig = new BarcodeImageConfiguration(new Size(500, 400), "/opt/usr/test-barcode-generate-new", BarcodeImageFormat.JPG);
         /// </code>
-        public BarcodeImageConfiguration(int width, int height, string path, BarcodeImageFormat imageFormat)
+        public BarcodeImageConfiguration(Size size, string path, BarcodeImageFormat imageFormat)
         {
-            Width = width;
-            Height = height;
+            if (size.Width <= 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(Size.Width), size.Width,
+                    "width can't be less than or equal to zero.");
+            }
+
+            if (size.Height <= 0)
+            {
+                throw new ArgumentOutOfRangeException(nameof(Size.Height), size.Height,
+                    "height can't be less than or equal to zero.");
+            }
+
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
+
+            ValidationUtil.ValidateEnum(typeof(BarcodeImageFormat), imageFormat);
+
+            Size = size;
             Path = path;
             Format = imageFormat;
         }
 
         /// <summary>
-        /// Gets the width of the generated image
+        /// Initializes a new instance of the <see cref="BarcodeImageConfiguration"/> class.
+        /// </summary>
+        /// <remarks>
+        /// The mediastorage privilege(http://tizen.org/privilege/mediastorage) is needed if image path is relevant to media storage.\n
+        /// The externalstorage privilege(http://tizen.org/privilege/externalstorage) is needed if image path is relevant to external storage.
+        /// </remarks>
+        /// <param name="width">The width of the image to be generated.</param>
+        /// <param name="height">The height of the image to be generated.</param>
+        /// <param name="path">The path to the file to be generated.</param>
+        /// <param name="imageFormat">The format of the output image.</param>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="width"/> is less than or equal to zero.\n
+        ///     - or -\n
+        ///     <paramref name="height"/> is less than or equal to zero.
+        /// </exception>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="ArgumentException"><paramref name="imageFormat"/> is invalid.</exception>
+        /// <code>
+        /// BarcodeImageConfiguration imageConfig = new BarcodeImageConfiguration(500, 400, "/opt/usr/test-barcode-generate-new", BarcodeImageFormat.JPG);
+        /// </code>
+        public BarcodeImageConfiguration(int width, int height, string path, BarcodeImageFormat imageFormat)
+            : this(new Size(width, height), path, imageFormat)
+        {
+        }
+
+        /// <summary>
+        /// Gets the size of the image.
+        /// </summary>
+        public Size Size { get; }
+
+        /// <summary>
+        /// Gets the width of the image.
         /// </summary>
-        public int Width { get; }
+        public int Width => Size.Width;
 
         /// <summary>
-        /// Gets the height of the generated image
+        /// Gets the height of the image.
         /// </summary>
-        public int Height { get; }
+        public int Height => Size.Height;
 
         /// <summary>
         /// Gets the path to the file that has to be generated
index 25c0ced..f1cf187 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for supported image formats for the barcode generation.
+    /// Specifies supported image formats for <see cref="BarcodeGenerator"/>
     /// </summary>
+    /// <seealso cref="BarcodeImageConfiguration"/>
     public enum BarcodeImageFormat
     {
         /// <summary>
-        /// Unavailable image format
-        /// </summary>
-        Unavailable = -1,
-        /// <summary>
         /// BMP image format
         /// </summary>
-        BMP,
+        Bmp,
         /// <summary>
         /// JPEG image format
         /// </summary>
-        JPG,
+        Jpeg,
         /// <summary>
         /// PNG image format
         /// </summary>
-        PNG,
-        /// <summary>
-        /// The number of supported image format
-        /// </summary>
-        NUM
+        Png
     }
 }
index 2b04dd6..0278696 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for supported barcode types.
+    /// Specifies the supported barcode types.
     /// </summary>
     /// <remarks>
     /// QR codes (versions 1 to 40) and set of 1D barcodes are supported
     /// </remarks>
+    /// <seealso cref="BarcodeDetector"/>
+    /// <seealso cref="BarcodeGenerator"/>
     public enum BarcodeType
     {
         /// <summary>
-        /// 2D barcode - Quick Response code
+        /// 2D barcode - Quick Response code.
         /// </summary>
         QR,
         /// <summary>
-        /// 1D barcode - Universal Product Code with 12-digit
+        /// 1D barcode - Universal Product Code with 12-digit.
         /// </summary>
-        UPC_A,
+        UpcA,
         /// <summary>
-        /// 1D barcode - Universal Product Code with 6-digit
+        /// 1D barcode - Universal Product Code with 6-digit.
         /// </summary>
-        UPC_E,
+        UpcE,
         /// <summary>
-        /// 1D barcode - International Article Number with 8-digit
+        /// 1D barcode - International Article Number with 8-digit.
         /// </summary>
-        EAN_8,
+        Ean8,
         /// <summary>
-        /// 1D barcode - International Article Number with 13-digit
+        /// 1D barcode - International Article Number with 13-digit.
         /// </summary>
-        EAN_13,
+        Ean13,
         /// <summary>
-        /// 1D barcode - Code 128
+        /// 1D barcode - Code 128.
         /// </summary>
-        CODE128,
+        Code128,
         /// <summary>
-        /// 1D barcode - Code 39
+        /// 1D barcode - Code 39.
         /// </summary>
-        CODE39,
+        Code39,
         /// <summary>
-        /// 1D barcode - Interleaved Two of Five
+        /// 1D barcode - Interleaved Two of Five.
         /// </summary>
-        I2_5,
-        /// <summary>
-        /// Undefined
-        /// </summary>
-        Undefined
+        I25
     }
 }
index 7e90566..fd9c1c2 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for Media Vision colorspace
+    /// Specifies colorspaces for MediaVision.
     /// </summary>
     public enum Colorspace
     {
         /// <summary>
-        /// The colorspace type is invalid
+        /// The colorspace type is invalid.
         /// </summary>
         Invalid,
         /// <summary>
-        /// The colorspace type is Y800
+        /// The colorspace type is Y800.
         /// </summary>
         Y800,
         /// <summary>
-        /// The colorspace type is I420
+        /// The colorspace type is I420.
         /// </summary>
         I420,
         /// <summary>
-        /// The colorspace type is NV12
+        /// The colorspace type is NV12.
         /// </summary>
         NV12,
         /// <summary>
-        /// The colorspace type is YV12
+        /// The colorspace type is YV12.
         /// </summary>
         YV12,
         /// <summary>
-        /// The colorspace type is NV21
+        /// The colorspace type is NV21.
         /// </summary>
         NV21,
         /// <summary>
-        /// The colorspace type is YUYV
+        /// The colorspace type is YUYV.
         /// </summary>
-        YUYV,
+        Yuyv,
         /// <summary>
-        /// The colorspace type is UYVY
+        /// The colorspace type is UYVY.
         /// </summary>
-        UYVY,
+        Uyvy,
         /// <summary>
-        /// The colorspace type is 422P
+        /// The colorspace type is 422P.
         /// </summary>
-        P422,
+        Yuv422P,
         /// <summary>
-        /// The colorspace type is RGB565
+        /// The colorspace type is RGB565.
         /// </summary>
-        RGB565,
+        Rgb565,
         /// <summary>
-        /// The colorspace type is RGB888
+        /// The colorspace type is RGB888.
         /// </summary>
-        RGB888,
+        Rgb888,
         /// <summary>
-        /// The colorspace type is RGBA
+        /// The colorspace type is RGBA.
         /// </summary>
-        RGBA
+        Rgba
     }
 }
index 18b7e39..a9a8347 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  */
 
 using System;
-using System.Collections.Generic;
+using System.Runtime.InteropServices;
 using static Interop.MediaVision;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents an abstract EngineConfiguration class.\n
-    /// It provides dictionary functionality. It means that it is possible to set (key, value) pairs to this class \n
-    /// and use them to transfer these values to the engine part underlying Media Vision API. \n
-    /// Information on which attributes can be set is provided together with concrete engines.
+    /// A base class for configuration classes.
     /// </summary>
     public abstract class EngineConfiguration : IDisposable
     {
-        internal IntPtr _engineHandle = IntPtr.Zero;
-        private readonly IDictionary<string, object> _config = new Dictionary<string, object>();
+        private IntPtr _handle = IntPtr.Zero;
         private bool _disposed = false;
 
-        /// <summary>
-        /// Constructor of the EngineConfig class.
-        /// </summary>
         internal EngineConfiguration()
         {
-            int ret = Interop.MediaVision.EngineConfig.Create(out _engineHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to create media vision engine.");
+            EngineConfig.Create(out _handle).Validate("Failed to create media vision engine.");
         }
 
-        /// <summary>
-        /// Destructor of the EngineConfig class.
-        /// </summary>
         ~EngineConfiguration()
         {
             Dispose(false);
         }
 
-        internal void Add<T>(string key, T value)
+        internal static IntPtr GetHandle(EngineConfiguration config)
         {
-            object val = (object)value;
-
-            if (!_config.ContainsKey(key))
+            if (config == null)
             {
-                _config.Add(key, val);
+                return IntPtr.Zero;
             }
-            else
-            {
-                int ret = 0;
-                if (typeof(T) == typeof(double))
-                {
-                    ret = Interop.MediaVision.EngineConfig.SetDouble(_engineHandle, key, (double)val);
-                }
-                else if (typeof(T) == typeof(int))
-                {
-                    ret = Interop.MediaVision.EngineConfig.SetInt(_engineHandle, key, (int)val);
-                }
-                else if (typeof(T) == typeof(bool))
-                {
-                    ret = Interop.MediaVision.EngineConfig.SetBool(_engineHandle, key, (bool)val);
-                }
-                else if (typeof(T) == typeof(string))
-                {
-                    ret = Interop.MediaVision.EngineConfig.SetString(_engineHandle, key, (string)val);
-                }
 
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to add attribute");
-                _config[key] = val;
+            if (config._disposed)
+            {
+                throw new ObjectDisposedException(config.GetType().Name);
             }
+
+            return config._handle;
+        }
+
+        internal void Set(string key, double value)
+        {
+            EngineConfig.SetDouble(Handle, key, value).Validate("Failed to set attribute");
+        }
+
+        internal void Set(string key, int value)
+        {
+            EngineConfig.SetInt(Handle, key, value).Validate("Failed to set attribute");
+        }
+
+
+        internal void Set(string key, bool value)
+        {
+            EngineConfig.SetBool(Handle, key, value).Validate("Failed to set attribute");
         }
 
-        internal object Get(string key)
+        internal void Set(string key, string value)
         {
-            if (_config.ContainsKey(key))
+            EngineConfig.SetString(Handle, key, value).Validate("Failed to set attribute");
+        }
+
+        internal int GetInt(string key)
+        {
+            int value = 0;
+            EngineConfig.GetInt(Handle, key, out value).Validate("Failed to get the value");
+            return value;
+        }
+
+        internal double GetDouble(string key)
+        {
+            double value = 0;
+            EngineConfig.GetDouble(Handle, key, out value).Validate("Failed to get the value");
+            return value;
+        }
+
+        internal bool GetBool(string key)
+        {
+            bool value = false;
+            EngineConfig.GetBool(Handle, key, out value).Validate("Failed to get the value");
+            return value;
+        }
+
+        internal string GetString(string key)
+        {
+            IntPtr ptr = IntPtr.Zero;
+
+            try
             {
-                return _config[key];
+                EngineConfig.GetString(Handle, key, out ptr).Validate("Failed to get the value");
+                return Marshal.PtrToStringAnsi(ptr);
             }
-            else
+            finally
             {
-                Log.Error(MediaVisionLog.Tag, "Attribute was not set");
-                return null;
+                Interop.Libc.Free(ptr);
             }
         }
 
@@ -108,13 +123,20 @@ namespace Tizen.Multimedia
                 return;
             }
 
-            if (disposing)
+            EngineConfig.Destroy(_handle);
+            _disposed = true;
+        }
+
+        internal IntPtr Handle
+        {
+            get
             {
-                // Free managed objects
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(nameof(EngineConfiguration));
+                }
+                return _handle;
             }
-
-            Interop.MediaVision.EngineConfig.Destroy(_engineHandle);
-            _disposed = true;
         }
     }
 }
index bd717cc..560ce59 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for supported QR code error correction level.
+    /// Specifies the supported QR code error correction level.
     /// </summary>
-    /// <remarks>
-    /// This is unavailable for 1D barcodes
-    /// </remarks>
     public enum ErrorCorrectionLevel
     {
         /// <summary>
-        /// Recovery up to 7% losses
+        /// Recovery up to 7% losses.
         /// </summary>
         Low,
         /// <summary>
-        /// Recovery up to 15% losses
+        /// Recovery up to 15% losses.
         /// </summary>
         Medium,
         /// <summary>
-        /// Recovery up to 25% losses
+        /// Recovery up to 25% losses.
         /// </summary>
         Quartile,
         /// <summary>
-        /// Recovery up to 30% losses
+        /// Recovery up to 30% losses.
         /// </summary>
-        High,
-        /// <summary>
-        /// Unavailable
-        /// </summary>
-        Unavailable
+        High
     }
 }
index b2fd3de..2ae27fd 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for eyes state type.
+    /// Specifies the eyes state types.
     /// </summary>
     public enum EyeCondition
     {
         /// <summary>
-        /// Eyes are open
+        /// Eyes are open.
         /// </summary>
         Open,
+
         /// <summary>
-        /// Eyes are closed
+        /// Eyes are closed.
         /// </summary>
         Closed,
+
         /// <summary>
-        /// The eyes condition wasn't determined
+        /// The eyes condition wasn't determined.
         /// </summary>
         NotFound
     }
diff --git a/src/Tizen.Multimedia/MediaVision/FaceDetectionConfiguration.cs b/src/Tizen.Multimedia/MediaVision/FaceDetectionConfiguration.cs
new file mode 100644 (file)
index 0000000..510219d
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="FaceDetector"/> instances.
+    /// </summary>
+    public class FaceDetectionConfiguration : EngineConfiguration
+    {
+        private const string KeyModelFilePath = "MV_FACE_DETECTION_MODEL_FILE_PATH";
+        private const string KeyRoiX = "MV_FACE_DETECTION_ROI_X";
+        private const string KeyRoiY = "MV_FACE_DETECTION_ROI_Y";
+        private const string KeyRoiWidth = "MV_FACE_DETECTION_ROI_WIDTH";
+        private const string KeyRoiHeight = "MV_FACE_DETECTION_ROI_HEIGHT";
+        private const string KeyMinWidth = "MV_FACE_DETECTION_MIN_SIZE_WIDTH";
+        private const string KeyMinHeight = "MV_FACE_DETECTION_MIN_SIZE_HEIGHT";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="FaceDetectionConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public FaceDetectionConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Sets or gets the face detection haarcascade xml file for face detection.
+        /// </summary>
+        /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception>
+        public string ModelFilePath
+        {
+            get
+            {
+                return GetString(KeyModelFilePath);
+            }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException(nameof(ModelFilePath), "ModeFilePath can't be null.");
+                }
+                Set(KeyModelFilePath, value);
+            }
+        }
+
+
+        /// <summary>
+        /// Gets or sets minimum height of face which will be detected.
+        /// </summary>
+        /// <remarks>
+        /// Default value is null (all detected faces will be applied), can be changed to specify the minimum face height.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        public int? MinHeight
+        {
+            get
+            {
+                int value = GetInt(KeyMinHeight);
+                if (value == -1) return null;
+                return value;
+            }
+            set
+            {
+                if (value.HasValue && value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(MinHeight), value,
+                        $"{nameof(MinHeight)} can't be less than zero.");
+                }
+
+                Set(KeyMinHeight, value ?? -1);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets minimum width of face which will be detected.
+        /// </summary>
+        /// <remarks>
+        /// Default value is null (all detected faces will be applied), can be changed to specify the minimum face width.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        public int? MinWidth
+        {
+            get
+            {
+                int value = GetInt(KeyMinWidth);
+                if (value == -1) return null;
+                return value;
+            }
+            set
+            {
+                if (value.HasValue && value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(MinWidth), value,
+                        $"{nameof(MinWidth)} can't be less than zero.");
+                }
+
+                Set(KeyMinWidth, value ?? -1);
+            }
+        }
+
+        private static readonly Rectangle DefaultRoi = new Rectangle(-1, -1, -1, -1);
+
+        private Rectangle? _roi;
+
+        /// <summary>
+        /// Sets or gets the roi of the face detection.
+        /// </summary>
+        /// <remarks>
+        /// Default value is null (the roi will be a full image) can be changed to specify the roi for face detection.
+        /// </remarks>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     The width of <paramref name="value"/> is less than or equal to zero.\n
+        ///     - or -\n
+        ///     The height of <paramref name="value"/> is less than or equal to zero.\n
+        ///     - or -\n
+        ///     The x position of <paramref name="value"/> is lsss than zero.\n
+        ///     - or -\n
+        ///     The y position of <paramref name="value"/> is lsss than zero.\n
+        /// </exception>
+        public Rectangle? Roi
+        {
+            get
+            {
+                return _roi;
+            }
+            set
+            {
+                if (value != null)
+                {
+                    ValidateRoi(value.Value);
+                }
+
+                SetRoi(value ?? DefaultRoi);
+
+                _roi = value;
+            }
+        }
+
+        private static void ValidateRoi(Rectangle roi)
+        {
+            if (roi.Width <= 0)
+            {
+                throw new ArgumentOutOfRangeException("Roi.Width", roi.Width,
+                    "The width of roi can't be less than or equal to zero.");
+            }
+
+            if (roi.Height <= 0)
+            {
+                throw new ArgumentOutOfRangeException("Roi.Height", roi.Height,
+                    "The height of roi can't be less than or equal to zero.");
+            }
+
+            if (roi.X < 0)
+            {
+                throw new ArgumentOutOfRangeException("Roi.X", roi.X,
+                    "The x position of roi can't be less than zero.");
+            }
+
+            if (roi.Y < 0)
+            {
+                throw new ArgumentOutOfRangeException("Roi.Y", roi.Y,
+                    "The y position of roi can't be less than zero.");
+            }
+        }
+
+        private void SetRoi(Rectangle roi)
+        {
+            Set(KeyRoiX, roi.X);
+            Set(KeyRoiY, roi.Y);
+            Set(KeyRoiWidth, roi.Width);
+            Set(KeyRoiHeight, roi.Height);
+        }
+    }
+}
index 4728efb..47792f6 100755 (executable)
  */
 
 using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
 using System.Threading.Tasks;
-using static Interop.MediaVision;
+using InteropFace = Interop.MediaVision.Face;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents the interface for media vision face detection.
+    /// Provides the ability to detect faces on image sources.
     /// </summary>
     public static class FaceDetector
     {
+
         /// <summary>
-        /// Performs face detection on the source for the engine_conf.\n
-        /// Use this function to launch face detection algorithm configured by @a config configuration.
+        /// Detects faces on the source.\n
         /// Each time when DetectAsync is called, a set of the detected faces at the media source are received asynchronously.
         /// </summary>
-        /// <param name="source">The source of the media where faces will be detected</param>
-        /// <param name="config">The configuration of engine will be used for detecting. If NULL, then default settings will be used.</param>
-        /// <returns>Returns the FaceDetectionResult asynchronously</returns>
-        /// <code>
-        ///
-        /// </code>
-        public static async Task<FaceDetectionResult> DetectAsync(MediaVisionSource source, FaceEngineConfiguration config = null)
+        /// <param name="source">The source of the media where faces will be detected.</param>
+        /// <returns>A task that represents the asynchronous detect operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     The feature is not supported.\n
+        ///     - or -\n
+        ///     The format of <paramref name="source"/> is not supported.
+        /// </exception>
+        public static async Task<Rectangle[]> DetectAsync(MediaVisionSource source)
+        {
+            return await DetectAsync(source, null);
+        }
+
+        /// <summary>
+        /// Detects faces on the source.\n
+        /// Each time when DetectAsync is called, a set of the detected faces at the media source are received asynchronously.
+        /// </summary>
+        /// <param name="source">The source of the media where faces will be detected.</param>
+        /// <param name="config">The configuration of engine will be used for detecting. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous detect operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public static async Task<Rectangle[]> DetectAsync(MediaVisionSource source,
+            FaceDetectionConfiguration config)
         {
             if (source == null)
             {
-                throw new ArgumentException("Invalid source");
+                throw new ArgumentNullException(nameof(source));
             }
 
-            TaskCompletionSource<FaceDetectionResult> tcsResult = new TaskCompletionSource<FaceDetectionResult>();
-            // Define native callback
-            Interop.MediaVision.Face.MvFaceDetectedCallback faceDetectedCb = (IntPtr sourceHandle, IntPtr engineCfgHandle, IntPtr facesLocations, int numberOfFaces, IntPtr userData) =>
+            TaskCompletionSource<Rectangle[]> tcs = new TaskCompletionSource<Rectangle[]>();
+
+            using (var cb = ObjectKeeper.Get(GetCallback(tcs)))
+            {
+                InteropFace.Detect(source.Handle, EngineConfiguration.GetHandle(config), cb.Target).
+                    Validate("Failed to perform face detection");
+
+                return await tcs.Task;
+            }
+        }
+
+        private static InteropFace.DetectedCallback GetCallback(TaskCompletionSource<Rectangle[]> tcs)
+        {
+            return (IntPtr sourceHandle, IntPtr engineConfig, Interop.MediaVision.Rectangle[] facesLocations,
+                int numberOfFaces, IntPtr _) =>
             {
                 try
                 {
-                    Log.Info(MediaVisionLog.Tag, String.Format("Faces detected, count : {0}", numberOfFaces));
-                    List<Rectangle> locations = new List<Rectangle>();
-                    if (numberOfFaces > 0)
+                    Log.Info(MediaVisionLog.Tag, $"Faces detected, count : {numberOfFaces}.");
+                    Rectangle[] locations = new Rectangle[numberOfFaces];
+                    for (int i = 0; i < numberOfFaces; i++)
                     {
-                        // Prepare list of locations
-                        for (int i = 0; i < numberOfFaces; i++)
-                        {
-                            Interop.MediaVision.Rectangle location = (Interop.MediaVision.Rectangle)Marshal.PtrToStructure(facesLocations, typeof(Interop.MediaVision.Rectangle));
-                            Rectangle rect = new Rectangle(new Point(location.x, location.y),
-                                new Size(location.width, location.height));
-                            Log.Info(MediaVisionLog.Tag, String.Format("Face {0} detected at : ({1}, {2})", i + 1, rect.Point.X, rect.Point.Y));
-                            locations.Add(rect);
-                            facesLocations = IntPtr.Add(facesLocations, sizeof(int) * 4);
-                        }
+                        locations[i] = facesLocations[i].ToApiStruct();
+                        Log.Info(MediaVisionLog.Tag, $"Face {0} detected : {locations}.");
                     }
 
-                    FaceDetectionResult result = new FaceDetectionResult()
-                    {
-                        Locations = locations
-                    };
-
-                    if (!tcsResult.TrySetResult(result))
+                    if (!tcs.TrySetResult(locations))
                     {
-                        Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                        tcsResult.TrySetException(new InvalidOperationException("Failed to set result"));
+                        Log.Error(MediaVisionLog.Tag, "Failed to set face detection result.");
                     }
                 }
-                catch (Exception ex)
+                catch (Exception e)
                 {
-                    Log.Info(MediaVisionLog.Tag, "exception :" + ex.ToString());
-                    tcsResult.TrySetException(ex);
+                    MultimediaLog.Info(MediaVisionLog.Tag, "Failed to handle face detection.", e);
+                    tcs.TrySetException(e);
                 }
             };
-
-            int ret = Interop.MediaVision.Face.Detect(source._sourceHandle, (config != null) ? config._engineHandle : IntPtr.Zero, faceDetectedCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to perform face detection.");
-            return await tcsResult.Task;
         }
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/FaceEngineConfiguration.cs b/src/Tizen.Multimedia/MediaVision/FaceEngineConfiguration.cs
deleted file mode 100755 (executable)
index b5b4b66..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents concrete EngineConfig for Face detection and recognition
-    /// </summary>
-    public class FaceEngineConfiguration : EngineConfiguration
-    {
-        // List of predefined keys
-        private const string _faceDetectionModelFilePathKey = "MV_FACE_DETECTION_MODEL_FILE_PATH";
-        private const string _faceRecognitionModelTypeKey = "MV_FACE_RECOGNITION_MODEL_TYPE";
-        private const string _faceDetectionRoiXKey = "MV_FACE_DETECTION_ROI_X";
-        private const string _faceDetectionRoiYKey = "MV_FACE_DETECTION_ROI_Y";
-        private const string _faceDetectionRoiWidthKey = "MV_FACE_DETECTION_ROI_WIDTH";
-        private const string _faceDetectionRoiHeightKey = "MV_FACE_DETECTION_ROI_HEIGHT";
-        private const string _faceDetectionMinWidthKey = "MV_FACE_DETECTION_MIN_SIZE_WIDTH";
-        private const string _faceDetectionMinHeightKey = "MV_FACE_DETECTION_MIN_SIZE_HEIGHT";
-        // Values are cached below to prevent interop calls for get operation
-        private string _faceDetectionModelFilePathValue;
-        private FaceRecognitionModelType _faceRecognitionModelTypeValue = FaceRecognitionModelType.LBPH;
-        private int _faceDetectionRoiXValue = -1;
-        private int _faceDetectionRoiYValue = -1;
-        private int _faceDetectionRoiWidthValue = -1;
-        private int _faceDetectionRoiHeightValue = -1;
-        private int _faceDetectionMinWidthValue = -1;
-        private int _faceDetectionMinHeightValue = -1;
-
-        /// <summary>
-        /// The default constructor of FaceEngineConfig class
-        /// </summary>
-        /// <code>
-        /// 
-        /// </code>
-        public FaceEngineConfiguration()
-            : base()
-        {
-            ModelFilePath = _faceDetectionModelFilePathValue;
-            ModelType = _faceRecognitionModelTypeValue; ;
-            MinimumHeight = _faceDetectionMinHeightValue;
-            MinimumWidth = _faceDetectionMinWidthValue;
-            RoiHeight = _faceDetectionRoiHeightValue;
-            RoiWidth = _faceDetectionRoiWidthValue;
-            RoiX = _faceDetectionRoiXValue;
-            RoiY = _faceDetectionRoiYValue;
-        }
-
-        /// <summary>
-        /// Sets and gets face detection haarcascade xml file attribute of the engine configuration.
-        /// </summary>
-        public string ModelFilePath
-        {
-            get
-            {
-                return _faceDetectionModelFilePathValue;
-            }
-
-            set
-            {
-                Add<string>(_faceDetectionModelFilePathKey, value);
-                _faceDetectionModelFilePathValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the method used for face recognition model learning attribute of the engine configuration.
-        /// </summary>
-        public FaceRecognitionModelType ModelType
-        {
-            get
-            {
-                return _faceRecognitionModelTypeValue;
-            }
-
-            set
-            {
-                if (value == FaceRecognitionModelType.Unknown)
-                {
-                    throw new ArgumentException("ModelType value is invalid");
-                }
-
-                Add<int>(_faceRecognitionModelTypeKey, (int)value);
-                _faceRecognitionModelTypeValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets minimum height of face which will be detected as attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// Default value is -1 (all detected faces will be applied) can be changed to specify the minimum face height.
-        /// </remarks>
-        public int MinimumHeight
-        {
-            get
-            {
-                return _faceDetectionMinHeightValue;
-            }
-
-            set
-            {
-                Add<int>(_faceDetectionMinHeightKey, value);
-                _faceDetectionMinHeightValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets minimum width of face which will be detected as attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// Default value is -1 (all detected faces will be applied) can be changed to specify the minimum face width.
-        /// </remarks>
-        public int MinimumWidth
-        {
-            get
-            {
-                return _faceDetectionMinWidthValue;
-            }
-
-            set
-            {
-                Add<int>(_faceDetectionMinWidthKey, value);
-                _faceDetectionMinWidthValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets height of face detection roi as attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// Default value is -1 (the roi will be a full image) can be changed to specify the roi for face detection.
-        /// </remarks>
-        public int RoiHeight
-        {
-            get
-            {
-                return _faceDetectionRoiHeightValue;
-            }
-
-            set
-            {
-                Add<int>(_faceDetectionRoiHeightKey, value);
-                _faceDetectionRoiHeightValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets width of face detection roi as attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// Default value is -1 (the roi will be a full image) can be changed to specify the roi for face detection
-        /// </remarks>
-        public int RoiWidth
-        {
-            get
-            {
-                return _faceDetectionRoiWidthValue;
-            }
-
-            set
-            {
-                Add<int>(_faceDetectionRoiWidthKey, value);
-                _faceDetectionRoiWidthValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets X coordinate of face detection roi as attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// Default value is -1 (the roi will be a full image) can be changed to specify the roi for face detection
-        /// </remarks>
-        public int RoiX
-        {
-            get
-            {
-                return _faceDetectionRoiXValue;
-            }
-
-            set
-            {
-                Add<int>(_faceDetectionRoiXKey, value);
-                _faceDetectionRoiXValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets Y coordinate of face detection roi as attribute of the engine configuration.
-        /// </summary>
-        /// <remarks>
-        /// Default value is -1 (the roi will be a full image) can be changed to specify the roi for face detection
-        /// </remarks>
-        public int RoiY
-        {
-            get
-            {
-                return _faceDetectionRoiYValue;
-            }
-
-            set
-            {
-                Add<int>(_faceDetectionRoiYKey, value);
-                _faceDetectionRoiYValue = value;
-            }
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/FaceRecognitionConfiguration.cs b/src/Tizen.Multimedia/MediaVision/FaceRecognitionConfiguration.cs
new file mode 100644 (file)
index 0000000..56b2049
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="FaceRecognizer"/> instances.
+    /// </summary>
+    public class FaceRecognitionConfiguration : EngineConfiguration
+    {
+        private const string KeyModelType = "MV_FACE_RECOGNITION_MODEL_TYPE";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="FaceRecognitionConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="System.NotSupportedException">The feature is not supported.</exception>
+        public FaceRecognitionConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the method used for face recognition model learning.
+        /// Default value is <see cref="FaceRecognitionModelType.Lbph"/>.
+        /// </summary>
+        /// <exception cref="System.ArgumentException"><paramref name="value"/> is not valid.</exception>
+        public FaceRecognitionModelType ModelType
+        {
+            get
+            {
+                return (FaceRecognitionModelType)GetInt(KeyModelType);
+            }
+            set
+            {
+                ValidationUtil.ValidateEnum(typeof(FaceRecognitionModelType), value);
+                Set(KeyModelType, (int)value);
+            }
+        }
+
+    }
+}
index 682182c..dcbea29 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  */
 
 using System;
+using System.IO;
 using System.Runtime.InteropServices;
-using static Interop.MediaVision;
+using InteropModel = Interop.MediaVision.FaceRecognitionModel;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents face recognition model interface
+    /// Represents the face recognition model interface.
     /// </summary>
     public class FaceRecognitionModel : IDisposable
     {
-        internal IntPtr _recognitionModelHandle = IntPtr.Zero;
+        private IntPtr _handle = IntPtr.Zero;
         private bool _disposed = false;
 
         /// <summary>
-        /// Construct of FaceRecognitionModel class
+        /// Initializes a new instance of the <see cref="FaceRecognitionModel"/> class.
         /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
         public FaceRecognitionModel()
         {
-            int ret = Interop.MediaVision.FaceRecognitionModel.Create(out _recognitionModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to create FaceRecognitionModel.");
+            InteropModel.Create(out _handle).Validate("Failed to create FaceRecognitionModel");
         }
 
         /// <summary>
-        /// Construct of FaceRecognitionModel class which creates and loads recognition model from file.
+        /// Initializes a new instance of the <see cref="FaceRecognitionModel"/> class withe the specified path.
         /// </summary>
         /// <remarks>
-        /// FaceRecognitionModel is loaded from the absolute path directory.\n
-        /// Models has been saved by <see cref="Save()"/> function can be loaded with this function
+        /// Models have been saved by <see cref="Save()"/> can be loaded.
         /// </remarks>
-        /// <param name="fileName">Name of path/file to load the model</param>
-        /// <seealso cref="Save()"/>
-        /// <code>
-        /// 
-        /// </code>
-        public FaceRecognitionModel(string fileName)
+        /// <param name="modelPath">Path to the model to load.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception>
+        /// <exception cref="FileNotFoundException"><paramref name="modelPath"/> is invalid.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     The feature is not supported.\n
+        ///     - or -\n
+        ///     <paramref name="modelPath"/> is not supported format.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception>
+        /// <seealso cref="Save(string)"/>
+        public FaceRecognitionModel(string modelPath)
         {
-            int ret = Interop.MediaVision.FaceRecognitionModel.Load(fileName, out _recognitionModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to load FaceRecognitionModel from file.");
+            if (modelPath == null)
+            {
+                throw new ArgumentNullException(nameof(modelPath));
+            }
+
+            InteropModel.Load(modelPath, out _handle).
+                Validate("Failed to load FaceRecognitionModel from file");
         }
 
-        /// <summary>
-        /// Destructor of the FaceRecognitionModel class.
-        /// </summary>
         ~FaceRecognitionModel()
         {
             Dispose(false);
         }
 
         /// <summary>
-        /// Gets labels list
+        /// Gets labels that had been learned by the model.
         /// </summary>
-        public int[] FaceLabels
+        public int[] Labels
         {
             get
             {
-                IntPtr labelsArrayPtr;
-                uint numOfLabels = 0;
-                int ret = Interop.MediaVision.FaceRecognitionModel.QueryLabels(_recognitionModelHandle, out labelsArrayPtr, out numOfLabels);
-                if (ret != 0)
+                IntPtr unmangedArray = IntPtr.Zero;
+                try
                 {
-                    Tizen.Log.Error(MediaVisionLog.Tag, "Failed to get face labels");
-                    return null;
-                }
+                    uint numOfLabels = 0;
+
+                    InteropModel.QueryLabels(Handle, out unmangedArray, out numOfLabels).
+                        Validate("Failed to retrieve face labels.");
 
-                int[] labels = new int[numOfLabels];
-                for (int i = 0; i < numOfLabels; i++)
+                    int[] labels = new int[numOfLabels];
+                    Marshal.Copy(unmangedArray, labels, 0, (int)numOfLabels);
+
+                    return labels;
+                }
+                finally
                 {
-                    labels[i] = Marshal.ReadInt32(labelsArrayPtr);
-                    labelsArrayPtr = IntPtr.Add(labelsArrayPtr, sizeof(int));
+                    if (unmangedArray != IntPtr.Zero)
+                    {
+                        Interop.Libc.Free(unmangedArray);
+                    }
                 }
-
-                return labels;
             }
         }
 
         /// <summary>
-        /// Calls this method to save recognition model to the file.
+        /// Saves the recognition model to the file.
         /// </summary>
-        /// <remarks>
-        /// RecognitionModel is saved to the absolute path directory.
-        /// </remarks>
-        /// <param name="fileName">Name of the path/file to save the model</param>
-        /// <code>
-        /// 
-        /// </code>
-        public void Save(string fileName)
+        /// <param name="path">Path to the file to save the model.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception>
+        /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception>
+        public void Save(string path)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
+
+            var ret = InteropModel.Save(path, Handle);
+
+            if (ret == MediaVisionError.InvalidPath)
+            {
+                throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist.");
+            }
+
+            ret.Validate("Failed to save recognition model to file");
+        }
+
+        private MediaVisionError InvokeAdd(MediaVisionSource source, int label, Rectangle? area)
         {
-            if (string.IsNullOrEmpty(fileName))
+            if (area != null)
             {
-                throw new ArgumentException("Invalid file name");
+                var rect = area.Value.ToMarshalable();
+                return InteropModel.Add(source.Handle, Handle, ref rect, label);
             }
 
-            int ret = Interop.MediaVision.FaceRecognitionModel.Save(fileName, _recognitionModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to save recognition model to file");
+            return InteropModel.Add(source.Handle, Handle, IntPtr.Zero, label);
         }
 
         /// <summary>
-        /// Adds face image example to be used for face recognition model learning with <see cref="Learn()"/>.
+        /// Adds face image example to be used for face recognition model learning.
         /// </summary>
-        /// <param name="source">Source that contains face image</param>
-        /// <param name="faceLabel">The label that identifies face for which example is adding. Specify the same labels for the face images of a single person when calling this method. Has to be unique for each face</param>
-        /// <param name="location">The rectangular location of the face image at the source image.</param>
-        /// <code>
-        /// 
-        /// </code>
-        public void Add(MediaVisionSource source, int faceLabel, Rectangle location = null)
+        /// <param name="source">The <see cref="MediaVisionSource"/> that contains face image.</param>
+        /// <param name="label">The label that identifies face for which example is adding.
+        ///     Specify the same labels for the face images of a single person when calling this method.
+        ///     Has to be unique for each face</param>
+        /// <param name="area">The rectangular location of the face image at the source image.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="FaceRecognitionModel"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already been dispose of.
+        /// </exception>
+        /// <seealso cref="Learn(FaceRecognitionConfiguration)"/>
+        public void Add(MediaVisionSource source, int label)
         {
             if (source == null)
             {
                 throw new ArgumentException("Invalid source");
             }
 
-            IntPtr ptr = IntPtr.Zero;
-            if (location != null)
+            InvokeAdd(source, label, null).Validate("Failed to add face example image");
+        }
+
+        /// <summary>
+        /// Adds face image example to be used for face recognition model learning.
+        /// </summary>
+        /// <param name="source">The <see cref="MediaVisionSource"/> that contains face image.</param>
+        /// <param name="label">The label that identifies face for which example is adding.
+        ///     Specify the same labels for the face images of a single person when calling this method.
+        ///     Has to be unique for each face</param>
+        /// <param name="area">The rectangular region of the face image at the source image.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="FaceRecognitionModel"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already been dispose of.
+        /// </exception>
+        /// <seealso cref="Learn(FaceRecognitionConfiguration)"/>
+        public void Add(MediaVisionSource source, int label, Rectangle area)
+        {
+            if (source == null)
             {
-                Interop.MediaVision.Rectangle rectangle = new Interop.MediaVision.Rectangle()
-                {
-                    width = location.Width,
-                    height = location.Height,
-                    x = location.Point.X,
-                    y = location.Point.Y
-                };
-                ptr = Marshal.AllocHGlobal(Marshal.SizeOf(rectangle));
-                Marshal.StructureToPtr(rectangle, ptr, false);
+                throw new ArgumentException("Invalid source");
             }
 
-            int ret = Interop.MediaVision.FaceRecognitionModel.Add(source._sourceHandle, _recognitionModelHandle, ptr, faceLabel);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to add face example image");
+            InvokeAdd(source, label, area).Validate("Failed to add face example image");
         }
 
         /// <summary>
-        /// Removes from RecognitionModel all collected with <see cref="Add()"/> function face examples labeled with faceLabel.
+        /// Removes all face examples added with the specified label.
         /// </summary>
-        /// <param name="faceLabel">The label that identifies face for which examples will be removed from the RecognitionModel.</param>
-        /// <code>
-        /// 
-        /// </code>
-        public void Remove(int faceLabel)
+        /// <param name="label">The label that identifies face for which examples will be removed.</param>
+        /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception>
+        /// <returns>true if the examples are successfully removed; otherwise, false if there is no example labeled with the specified label.</returns>
+        /// <seealso cref="Add(MediaVisionSource, int)"/>
+        /// <seealso cref="Add(MediaVisionSource, int, Rectangle)"/>
+        public bool Remove(int label)
         {
-            int ret = Interop.MediaVision.FaceRecognitionModel.Remove(_recognitionModelHandle, ref faceLabel);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to remove image example");
+            var ret = InteropModel.Remove(Handle, ref label);
+
+            if (ret == MediaVisionError.KeyNotAvailable)
+            {
+                return false;
+            }
+
+            ret.Validate("Failed to remove image example");
+            return true;
         }
 
         /// <summary>
-        /// Removes all image examples known by RecognitionModel.
+        /// Removes all face examples.
         /// </summary>
-        /// <code>
-        /// 
-        /// </code>
+        /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception>
         public void Reset()
         {
-            int ret = Interop.MediaVision.FaceRecognitionModel.Reset(_recognitionModelHandle, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to remove image example");
+            InteropModel.Reset(Handle).Validate("Failed to reset image example");
         }
 
+
         /// <summary>
         /// Learns face recognition model.
         /// </summary>
         /// <remarks>
         /// Before you start learning process, face recognition models has to be filled with training data - face image examples.
-        /// These examples has to be provided by <see cref="Add()"/> function. Usually, recognition accuracy is increased
-        /// when number of not identical examples is large. But it depends on the used learning algorithm.
+        /// These examples has to be provided by <see cref="Add(MediaVisionSource, int)"/> or <see cref="Add(MediaVisionSource, int, Rectangle)"/>.
+        /// Recognition accuracy is usually increased when the different examples of the identical face are added more and more.
+        /// But it depends on the used learning algorithm.
+        /// </remarks>
+        /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception>
+        /// <exception cref="InvalidOperationException">No examples added.</exception>
+        /// <seealso cref="Add(MediaVisionSource, int)"/>
+        /// <seealso cref="Add(MediaVisionSource, int, Rectangle)"/>
+        public void Learn()
+        {
+            Learn(null);
+        }
+
+        /// <summary>
+        /// Learns face recognition model with <see cref="FaceRecognitionConfiguration"/>.
+        /// </summary>
+        /// <remarks>
+        /// Before you start learning process, face recognition models has to be filled with training data - face image examples.
+        /// These examples has to be provided by <see cref="Add(MediaVisionSource, int)"/> or <see cref="Add(MediaVisionSource, int, Rectangle)"/>.
+        /// Recognition accuracy is usually increased when the different examples of the identical face are added more and more.
+        /// But it depends on the used learning algorithm.
         /// </remarks>
-        /// <param name="config">The configuration of engine will be used for learning of the recognition models. If NULL, then default settings will be used</param>
-        /// <code>
-        /// 
-        /// </code>
-        public void Learn(FaceEngineConfiguration config = null)
+        /// <param name="config">The configuration used for learning of the recognition models. This value can be null.</param>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="FaceRecognitionModel"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="InvalidOperationException">No examples added.</exception>
+        /// <seealso cref="Add(MediaVisionSource, int)"/>
+        /// <seealso cref="Add(MediaVisionSource, int, Rectangle)"/>
+        public void Learn(FaceRecognitionConfiguration config)
         {
-            int ret = Interop.MediaVision.FaceRecognitionModel.Learn((config != null) ? config._engineHandle : IntPtr.Zero, _recognitionModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to learn");
+            InteropModel.Learn(EngineConfiguration.GetHandle(config), Handle).
+                Validate("Failed to learn");
         }
 
         public void Dispose()
@@ -201,13 +272,20 @@ namespace Tizen.Multimedia
                 return;
             }
 
-            if (disposing)
+            InteropModel.Destroy(_handle);
+            _disposed = true;
+        }
+
+        internal IntPtr Handle
+        {
+            get
             {
-                // Free managed objects
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(nameof(FaceRecognitionModel));
+                }
+                return _handle;
             }
-
-            Interop.MediaVision.FaceRecognitionModel.Destroy(_recognitionModelHandle);
-            _disposed = true;
         }
     }
 }
index c5865ef..d38df3c 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for face recognition model learning attribute of the engine configuration.
+    /// Specifies the face recognition model learning algorithms.
     /// </summary>
     public enum FaceRecognitionModelType
     {
         /// <summary>
-        /// Unknown method
+        /// Eigenfaces.
         /// </summary>
-        Unknown = 0,
-        /// <summary>
-        /// Eigenfaces
-        /// </summary>
-        EigenFaces,
+        EigenFaces = 1,
+
         /// <summary>
-        /// Fisherfaces
+        /// Fisherfaces.
         /// </summary>
         FisherFaces,
+
         /// <summary>
-        /// Local Binary Patterns Histograms (LBPH) - This is the default type
+        /// Local Binary Patterns Histograms (LBPH); The default type.
         /// </summary>
-        LBPH
+        Lbph
     }
 }
index f702d6f..b3af289 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents result of face recognition operation.
+    /// Represents result of <see cref="FaceRecognizer"/> operations.
     /// </summary>
     public class FaceRecognitionResult
     {
-        internal FaceRecognitionResult()
+        internal FaceRecognitionResult(bool recognized, double confidence, int label, Rectangle? area)
         {
+            Success = recognized;
+            Label = label;
+            Area = area;
+            Confidence = confidence;
         }
 
         /// <summary>
+        /// Gets the value indicating the recognition is successful.
+        /// </summary>
+        public bool Success { get; }
+
+        /// <summary>
         /// Gets the label of the recognized face.
         /// </summary>
-        public int Label { get; internal set; }
+        public int Label { get; }
 
         /// <summary>
         /// Gets the location of the recognized face.
         /// </summary>
-        public Rectangle Location { get; internal set; }
+        public Rectangle? Area { get; }
 
         /// <summary>
         /// The confidence of the recognition_model that face has been recognized correctly (value from 0.0 to 1.0).
@@ -41,6 +50,6 @@ namespace Tizen.Multimedia
         /// threshold for this value can be high (0.85-0.95). If model was learned for small amount of examples,
         /// then threshold can be reduced (0.5-0.85).
         /// </summary>
-        public double Confidence { get; internal set; }
+        public double Confidence { get; }
     }
 }
index e793bfb..a914b4a 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 using System;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
-using static Interop.MediaVision;
+using InteropFace = Interop.MediaVision.Face;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents an interface for Face recognition functionalities.
-    /// It also contains APIs which perform facial expression recognition and eye condition recognition.
+    /// Provides the ability to recognize faces, face expressions and eye condition on image sources.
     /// </summary>
     public static class FaceRecognizer
     {
+
+        /// <summary>
+        /// Performs face recognition on the source with <see cref="FaceRecognitionModel"/>.
+        /// </summary>
+        /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param>
+        /// <param name="recognitionModel">The <see cref="FaceRecognitionConfiguration"/> to be used for recognition.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="recognitionModel"/> is null.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception>
+        /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception>
+        public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source,
+            FaceRecognitionModel recognitionModel)
+        {
+            return await InvokeRecognizeAsync(source, recognitionModel, null, null);
+        }
+
+        /// <summary>
+        /// Performs face recognition on the source with <see cref="FaceRecognitionModel"/> and a bounding box.
+        /// </summary>
+        /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param>
+        /// <param name="recognitionModel">The <see cref="FaceRecognitionModel"/> to be used for recognition.</param>
+        /// <param name="bound">Rectangular box bounding face image on the source.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="recognitionModel"/> is null.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception>
+        /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception>
+        public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source,
+            FaceRecognitionModel recognitionModel, Rectangle bound)
+        {
+            return await InvokeRecognizeAsync(source, recognitionModel, bound, null);
+        }
+
         /// <summary>
-        /// Performs face recognition on the source image synchronously.
+        /// Performs face recognition on the source with <see cref="FaceRecognitionModel"/> and <see cref="FaceRecognitionConfiguration"/>.
         /// </summary>
-        /// <param name="source">The source of the media to recognize face(s) for</param>
-        /// <param name="recognitionModel">The model to be used for recognition</param>
-        /// <param name="config">The configuration of engine will be used for recognition. If NULL, then default settings will be used</param>
-        /// <param name="location">Rectangular box bounding face image on the source. If NULL, then full source will be analyzed</param>
-        /// <returns>Returns the FaceRecognitionResult asynchronously</returns>
-        /// <code>
-        /// 
-        /// </code>
-        public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source, FaceRecognitionModel recognitionModel, FaceEngineConfiguration config = null, Rectangle location = null)
+        /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param>
+        /// <param name="recognitionModel">The <see cref="FaceRecognitionModel"/> to be used for recognition.</param>
+        /// <param name="config">The configuration used for recognition. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="recognitionModel"/> is null.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception>
+        public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source,
+            FaceRecognitionModel recognitionModel, FaceRecognitionConfiguration config)
         {
-            if (source == null || recognitionModel == null)
+            return await InvokeRecognizeAsync(source, recognitionModel, null, config);
+        }
+
+
+        /// <summary>
+        /// Performs face recognition on the source  with <see cref="FaceRecognitionModel"/>, <see cref="FaceRecognitionConfiguration"/>
+        /// and a bounding box.
+        /// </summary>
+        /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param>
+        /// <param name="recognitionModel">The <see cref="FaceRecognitionModel"/> to be used for recognition.</param>
+        /// <param name="bound">Rectangular box bounding face image on the source.</param>
+        /// <param name="config">The <see cref="FaceRecognitionConfiguration"/> used for recognition. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="recognitionModel"/> is null.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception>
+        public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source,
+            FaceRecognitionModel recognitionModel, Rectangle bound, FaceRecognitionConfiguration config)
+        {
+            return await InvokeRecognizeAsync(source, recognitionModel, bound, config);
+        }
+
+        private static MediaVisionError InvokeRecognize(IntPtr sourceHandle, IntPtr modelHandle,
+            IntPtr configHandle, InteropFace.RecognizedCallback cb, Rectangle? area)
+        {
+            if (area == null)
             {
-                throw new ArgumentException("Invalid parameter");
+                return InteropFace.Recognize(sourceHandle, modelHandle, configHandle, IntPtr.Zero, cb);
             }
 
-            IntPtr locationPtr = IntPtr.Zero;
-            if (location != null)
+            var rect = area.Value.ToMarshalable();
+            return InteropFace.Recognize(sourceHandle, modelHandle, configHandle, ref rect, cb);
+        }
+
+        private static async Task<FaceRecognitionResult> InvokeRecognizeAsync(MediaVisionSource source,
+            FaceRecognitionModel recognitionModel, Rectangle? area,
+            FaceRecognitionConfiguration config)
+        {
+            if (source == null)
             {
-                Interop.MediaVision.Rectangle rectangle = new Interop.MediaVision.Rectangle()
-                {
-                    width = location.Width,
-                    height = location.Height,
-                    x = location.Point.X,
-                    y = location.Point.Y
-                };
-                locationPtr = Marshal.AllocHGlobal(Marshal.SizeOf(rectangle));
-                Marshal.StructureToPtr(rectangle, locationPtr, false);
+                throw new ArgumentNullException(nameof(source));
+            }
+            if (recognitionModel == null)
+            {
+                throw new ArgumentNullException(nameof(recognitionModel));
             }
 
-            TaskCompletionSource<FaceRecognitionResult> tcsResult = new TaskCompletionSource<FaceRecognitionResult>();
+            TaskCompletionSource<FaceRecognitionResult> tcs = new TaskCompletionSource<FaceRecognitionResult>();
 
-            // Define native callback
-            Interop.MediaVision.Face.MvFaceRecognizedCallback faceRecognizedCb = (IntPtr sourceHandle, IntPtr recognitionModelHandle, IntPtr engineCfgHandle, IntPtr faceLocationPtr, IntPtr faceLabelPtr, double confidence, IntPtr userData) =>
+            using (var cb = ObjectKeeper.Get(GetRecognizedCallback(tcs)))
             {
-                try
-                {
-                    int faceLabel = 0;
-                    if (faceLabelPtr != IntPtr.Zero)
-                    {
-                        faceLabel = Marshal.ReadInt32(faceLabelPtr);
-                    }
+                InvokeRecognize(source.Handle, recognitionModel.Handle, EngineConfiguration.GetHandle(config),
+                    cb.Target, area).Validate("Failed to perform face recognition.");
 
-                    Rectangle faceLocation = null;
-                    if (faceLocationPtr != IntPtr.Zero)
-                    {
-                        Interop.MediaVision.Rectangle loc = (Interop.MediaVision.Rectangle)Marshal.PtrToStructure(faceLocationPtr, typeof(Interop.MediaVision.Rectangle));
-                        faceLocation = new Rectangle()
-                        {
-                            Width = loc.width,
-                            Height = loc.height,
-                            Point = new Point(loc.x, loc.y)
-                        };
-                        Log.Info(MediaVisionLog.Tag, String.Format("Face label {0} recognized at : ({1}, {2}), Width : {3}, Height : {4}, confidence : {5}", faceLabel, faceLocation.Point.X, faceLocation.Point.Y, faceLocation.Width, faceLocation.Height, confidence));
-                    }
+                return await tcs.Task;
+            }
+        }
 
-                    FaceRecognitionResult result = new FaceRecognitionResult()
-                    {
-                        Location = faceLocation,
-                        Label = faceLabel,
-                        Confidence = confidence
-                    };
+        private static FaceRecognitionResult CreateRecognitionResult(
+             IntPtr faceLocationPtr, IntPtr faceLabelPtr, double confidence)
+        {
+            int faceLabel = 0;
+            if (faceLabelPtr != IntPtr.Zero)
+            {
+                faceLabel = Marshal.ReadInt32(faceLabelPtr);
+            }
 
-                    if (!tcsResult.TrySetResult(result))
+            Rectangle? faceLocation = null;
+            if (faceLocationPtr != IntPtr.Zero)
+            {
+                var area = Marshal.PtrToStructure<Interop.MediaVision.Rectangle>(faceLocationPtr);
+                faceLocation = area.ToApiStruct();
+            }
+
+            return new FaceRecognitionResult(faceLabelPtr != IntPtr.Zero, confidence, faceLabel, faceLocation);
+        }
+
+        private static InteropFace.RecognizedCallback GetRecognizedCallback(
+            TaskCompletionSource<FaceRecognitionResult> tcs)
+        {
+            return (IntPtr sourceHandle, IntPtr recognitionModelHandle,
+                IntPtr engineCfgHandle, IntPtr faceLocationPtr, IntPtr faceLabelPtr, double confidence, IntPtr _) =>
+            {
+                try
+                {
+                    if (!tcs.TrySetResult(CreateRecognitionResult(faceLocationPtr, faceLabelPtr, confidence)))
                     {
-                        Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                        tcsResult.TrySetException(new InvalidOperationException("Failed to set result"));
+                        Log.Error(MediaVisionLog.Tag, "Failed to set result");
                     }
                 }
-                catch (Exception ex)
+                catch (Exception e)
                 {
-                    Log.Info(MediaVisionLog.Tag, "exception :" + ex.ToString());
-                    tcsResult.TrySetException(ex);
+                    MultimediaLog.Error(MediaVisionLog.Tag, "Setting recognition result failed.", e);
+                    tcs.TrySetException(e);
                 }
             };
+        }
 
-
-            int ret = Interop.MediaVision.Face.Recognize(source._sourceHandle, recognitionModel._recognitionModelHandle,
-                            (config != null) ? config._engineHandle : IntPtr.Zero, locationPtr, faceRecognizedCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to perform face recognition.");
-
-            return await tcsResult.Task;
+        /// <summary>
+        /// Determines eye-blink condition on media source.
+        /// </summary>
+        /// <param name="source">The source of the media to recognize eye-blink condition for.</param>
+        /// <param name="bound">The bounding the face at the source.</param>
+        /// <param name="config">The configuration used for eye-blink condition recognition. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public static async Task<EyeCondition> RecognizeEyeConditionAsync(MediaVisionSource source,
+            Rectangle bound)
+        {
+            return await RecognizeEyeConditionAsync(source, bound, null);
         }
 
         /// <summary>
-        /// Determines eye-blink condition for @a location on media source.
+        /// Determines eye-blink condition on media source.
         /// </summary>
-        /// <param name="source">The source of the media to recognize eye-blink condition for</param>
-        /// <param name="location">The location bounding the face at the source</param>
-        /// <param name="config">The configuration of engine will be used for eye-blink condition recognition. If NULL, the default configuration will be used</param>
-        /// <returns>Returns the EyeCondition asynchronously</returns>
-        public static async Task<EyeCondition> RecognizeEyeConditionAsync(MediaVisionSource source, Rectangle location, FaceEngineConfiguration config = null)
+        /// <param name="source">The source of the media to recognize eye-blink condition for.</param>
+        /// <param name="bound">The bounding the face at the source.</param>
+        /// <param name="config">The configuration used for eye-blink condition recognition. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public static async Task<EyeCondition> RecognizeEyeConditionAsync(MediaVisionSource source,
+            Rectangle bound, FaceRecognitionConfiguration config)
         {
-            if (source == null || location == null)
+            if (source == null)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new ArgumentNullException(nameof(source));
             }
 
-            Interop.MediaVision.Rectangle rectangle = new Interop.MediaVision.Rectangle()
-            {
-                width = location.Width,
-                height = location.Height,
-                x = location.Point.X,
-                y = location.Point.Y
-            };
+            TaskCompletionSource<EyeCondition> tcs = new TaskCompletionSource<EyeCondition>();
 
-            TaskCompletionSource<EyeCondition> tcsResult = new TaskCompletionSource<EyeCondition>();
-
-            // Define native callback
-            Interop.MediaVision.Face.MvFaceEyeConditionRecognizedCallback eyeConditionRecognizedCb = (IntPtr sourceHandle, IntPtr engineCfgHandle, Interop.MediaVision.Rectangle faceLocation, EyeCondition eyeCondition, IntPtr userData) =>
+            InteropFace.EyeConditionRecognizedCallback cb = (IntPtr sourceHandle, IntPtr engineCfgHandle,
+                Interop.MediaVision.Rectangle faceLocation, EyeCondition eyeCondition, IntPtr _) =>
             {
-                Log.Info(MediaVisionLog.Tag, String.Format("Eye condition recognized, eye condition : {0}", eyeCondition));
-                if (!tcsResult.TrySetResult(eyeCondition))
+                Log.Info(MediaVisionLog.Tag, $"Eye condition recognized, eye condition : {eyeCondition}");
+                if (!tcs.TrySetResult(eyeCondition))
                 {
-                    Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                    tcsResult.TrySetException(new InvalidOperationException("Failed to set result"));
+                    Log.Error(MediaVisionLog.Tag, "Failed to set eye condition result");
                 }
             };
 
-            int ret = Interop.MediaVision.Face.RecognizeEyeCondition(source._sourceHandle, (config != null) ? config._engineHandle : IntPtr.Zero,
-                             rectangle, eyeConditionRecognizedCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to perform eye condition recognition.");
+            using (var cbKeeper = ObjectKeeper.Get(cb))
+            {
+                InteropFace.RecognizeEyeCondition(source.Handle, EngineConfiguration.GetHandle(config),
+                    bound.ToMarshalable(), cb).Validate("Failed to perform eye condition recognition.");
 
-            return await tcsResult.Task;
+                return await tcs.Task;
+            }
         }
 
         /// <summary>
-        /// Determines facial expression for @a location on media source.
+        /// Determines facial expression on media source.
         /// </summary>
-        /// <param name="source">The source of the media to recognize facial expression for</param>
-        /// <param name="location">The location bounding the face at the source</param>
-        /// <param name="config">The configuration of engine to be used for expression recognition</param>
-        /// <returns>Returns the FacialExpression asynchronously</returns>
-        public static async Task<FacialExpression> RecognizeFacialExpressionAsync(MediaVisionSource source, Rectangle location, FaceEngineConfiguration config = null)
+        /// <param name="source">The source of the media to recognize facial expression for.</param>
+        /// <param name="bound">The location bounding the face at the source.</param>
+        /// <param name="config">The configuration used for expression recognition.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public static async Task<FacialExpression> RecognizeFacialExpressionAsync(MediaVisionSource source,
+            Rectangle bound)
         {
-            if (source == null || location == null)
-            {
-                throw new ArgumentException("Invalid parameter");
-            }
+            return await RecognizeFacialExpressionAsync(source, bound, null);
+        }
 
-            Interop.MediaVision.Rectangle rectangle = new Interop.MediaVision.Rectangle()
+        /// <summary>
+        /// Determines facial expression on media source.
+        /// </summary>
+        /// <param name="source">The source of the media to recognize facial expression for.</param>
+        /// <param name="bound">The location bounding the face at the source.</param>
+        /// <param name="config">The configuration used for expression recognition. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public static async Task<FacialExpression> RecognizeFacialExpressionAsync(MediaVisionSource source,
+            Rectangle bound, FaceRecognitionConfiguration config)
+        {
+            if (source == null)
             {
-                width = location.Width,
-                height = location.Height,
-                x = location.Point.X,
-                y = location.Point.Y
-            };
+                throw new ArgumentNullException(nameof(source));
+            }
 
             TaskCompletionSource<FacialExpression> tcsResult = new TaskCompletionSource<FacialExpression>();
 
-            // Define native callback
-            Interop.MediaVision.Face.MvFaceFacialExpressionRecognizedCallback facialExpressionRecognizedCb = (IntPtr sourceHandle, IntPtr engineCfgHandle, Interop.MediaVision.Rectangle faceLocation, FacialExpression facialExpression, IntPtr userData) =>
+           InteropFace.MvFaceFacialExpressionRecognizedCallback cb = (IntPtr sourceHandle, IntPtr engineCfgHandle,
+               Interop.MediaVision.Rectangle faceLocation, FacialExpression facialExpression, IntPtr _) =>
             {
-                Log.Info(MediaVisionLog.Tag, String.Format("Facial expression recognized, expression : {0}", facialExpression));
+                Log.Info(MediaVisionLog.Tag, $"Facial expression recognized, expression : {facialExpression}");
                 if (!tcsResult.TrySetResult(facialExpression))
                 {
-                    Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                    tcsResult.TrySetException(new InvalidOperationException("Failed to set result"));
+                    Log.Error(MediaVisionLog.Tag, "Failed to set facial result");
                 }
             };
 
-            int ret = Interop.MediaVision.Face.RecognizeFacialExpression(source._sourceHandle, (config != null) ? config._engineHandle : IntPtr.Zero,
-                             rectangle, facialExpressionRecognizedCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to perform facial expression recognition.");
+            using (var cbKeeper = ObjectKeeper.Get(cb))
+            {
+                InteropFace.RecognizeFacialExpression(source.Handle, EngineConfiguration.GetHandle(config),
+                    bound.ToMarshalable(), cb).
+                    Validate("Failed to perform facial expression recognition.");
 
-            return await tcsResult.Task;
+                return await tcsResult.Task;
+            }
         }
     }
 }
+
index 0a3bdf5..c49a61e 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 using System;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
-using static Interop.MediaVision;
+using InteropFace = Interop.MediaVision.Face;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class contains the Media Vision face tracking API which performs tracking
-    /// on <see cref="MediaVisionSource"/> for <see cref="FaceTrackingModel"/>
+    /// Provides the ability to track faces on image sources.
     /// </summary>
     public static class FaceTracker
     {
+
         /// <summary>
-        /// Performs face tracking on the @a source for the @a trackingModel.\n
-        /// Use this function to launch face tracking algorithm configured by @a config configuration using
-        /// @a trackingModel tracking model. Each time when this function is called, new location determined for the tracked face
-        /// and model confidence that location is determined correctly are returned.
+        /// Performs face tracking on the source with the trackingModel.
         /// </summary>
-        /// <param name="source">The source of the media to recognize face for</param>
-        /// <param name="trackingModel">The model will be used for tracking</param>
-        /// <param name="doLearn">The model learning flag. If it is set true then model will try to learn (if it supports learning feature), otherwise model will be not learned during the invoking tracking iteration. Learning process improves tracking correctness, but can decrease tracking performance</param>
-        /// <param name="config">The configuration of engine will be used for tracking. If NULL, the default configuration will be used.</param>
-        /// <returns>Returns the FaceTrackingResult with new location and confidence asynchronously</returns>
-        /// <code>
-        /// 
-        /// </code>
-        public static async Task<FaceTrackingResult> TrackAsync(MediaVisionSource source, FaceTrackingModel trackingModel, bool doLearn, FaceEngineConfiguration config = null)
+        /// <param name="source">The source of the media to recognize face for.</param>
+        /// <param name="trackingModel">The model will be used for tracking.</param>
+        /// <param name="doLearn">The value indicating whether model learning while tracking. If it is true then model will try to learn
+        /// (if it supports learning feature), otherwise model will be not learned during the invoking tracking iteration.
+        /// Learning process improves tracking correctness, but can decrease tracking performance</param>
+        /// <returns>A task that represents the asynchronous tracking operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="trackingModel"/> is null.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="trackingModel"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="InvalidOperationException"><paramref name="trackingModel"/> is not prepared.</exception>
+        public static async Task<FaceTrackingResult> TrackAsync(MediaVisionSource source,
+            FaceTrackingModel trackingModel, bool doLearn)
         {
-            if (source == null || trackingModel == null)
+            if (source == null)
+            {
+                throw new ArgumentNullException(nameof(source));
+            }
+            if (trackingModel == null)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new ArgumentNullException(nameof(trackingModel));
             }
 
-            TaskCompletionSource<FaceTrackingResult> tcsResult = new TaskCompletionSource<FaceTrackingResult>();
+            TaskCompletionSource<FaceTrackingResult> tcs = new TaskCompletionSource<FaceTrackingResult>();
 
-            // Define native callback
-            Interop.MediaVision.Face.MvFaceTrackedCallback faceTrackedCb = (IntPtr sourceHandle, IntPtr trackingModelHandle, IntPtr engineCfgHandle, IntPtr locationPtr, double confidence, IntPtr userData) =>
+            using (var cb = ObjectKeeper.Get(GetTrackCallback(tcs)))
+            {
+                InteropFace.Track(source.Handle, trackingModel.Handle, IntPtr.Zero,
+                    cb.Target, doLearn).Validate("Failed to perform face tracking.");
+
+                return await tcs.Task;
+            }
+        }
+
+        private static InteropFace.TrackedCallback GetTrackCallback(TaskCompletionSource<FaceTrackingResult> tcs)
+        {
+            return (IntPtr sourceHandle, IntPtr trackingModelHandle, IntPtr engineCfgHandle,
+                IntPtr locationPtr, double confidence, IntPtr _) =>
             {
                 try
                 {
-                    Quadrangle faceLocation = null;
+                    Quadrangle area = null;
                     if (locationPtr != IntPtr.Zero)
                     {
-                        Interop.MediaVision.Quadrangle location = (Interop.MediaVision.Quadrangle)Marshal.PtrToStructure(locationPtr, typeof(Interop.MediaVision.Quadrangle));
-                        faceLocation = new Quadrangle()
-                        {
-                            Points = new Point[4]
-                            {
-                            new Point(location.x1, location.y1),
-                            new Point(location.x2, location.y2),
-                            new Point(location.x3, location.y3),
-                            new Point(location.x4, location.y4)
-                            }
-                        };
-
-                        Log.Info(MediaVisionLog.Tag, String.Format("Tracked location : {0}, confidence : {1}", faceLocation.ToString(), confidence));
+                        area = Marshal.PtrToStructure<Interop.MediaVision.Quadrangle>(locationPtr).ToApiStruct();
                     }
 
-                    FaceTrackingResult result = new FaceTrackingResult()
-                    {
-                        Location = faceLocation,
-                        Confidence = confidence
-                    };
+                    Log.Info(MediaVisionLog.Tag, $"Tracked area : {area}, confidence : {confidence}");
 
-                    if (!tcsResult.TrySetResult(result))
+                    if (!tcs.TrySetResult(new FaceTrackingResult(locationPtr != IntPtr.Zero, confidence, area)))
                     {
-                        Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                        tcsResult.TrySetException(new InvalidOperationException("Failed to set result"));
+                        Log.Error(MediaVisionLog.Tag, "Failed to set tracking result");
                     }
                 }
-                catch (Exception ex)
+                catch (Exception e)
                 {
-                    Log.Info(MediaVisionLog.Tag, "exception :" + ex.ToString());
-                    tcsResult.TrySetException(ex);
+                    MultimediaLog.Error(MediaVisionLog.Tag, "Setting tracking result failed.", e);
+                    tcs.TrySetException(e);
                 }
             };
-
-            int ret = Interop.MediaVision.Face.Track(source._sourceHandle, trackingModel._trackingModelHandle, (config != null) ? config._engineHandle : IntPtr.Zero, faceTrackedCb, doLearn, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to perform face tracking.");
-
-            return await tcsResult.Task;
         }
     }
 }
index 6efe545..2b2a8e2 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  */
 
 using System;
-using System.Runtime.InteropServices;
-using static Interop.MediaVision;
+using System.IO;
+using InteropModel = Interop.MediaVision.FaceTrackingModel;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents face tracking model interface
+    /// Represents face tracking model.
     /// </summary>
     public class FaceTrackingModel : IDisposable
     {
-        internal IntPtr _trackingModelHandle = IntPtr.Zero;
+        private IntPtr _handle = IntPtr.Zero;
         private bool _disposed = false;
 
         /// <summary>
-        /// Construct of FaceTrackingModel class
+        /// Initializes a new instance of the <see cref="FaceTrackingModel"/> class.
         /// </summary>
-        /// <code>
-        /// var model = new FaceTrackingModel();
-        /// </code>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
         public FaceTrackingModel()
         {
-            int ret = Interop.MediaVision.FaceTrackingModel.Create(out _trackingModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to create FaceTrackingModel.");
+            InteropModel.Create(out _handle).Validate("Failed to create FaceTrackingModel.");
         }
 
         /// <summary>
-        /// Construct of FaceTrackingModel class which creates and loads tracking model from file.
+        /// Initializes a new instance of the <see cref="FaceTrackingModel"/> class with the specified path.
         /// </summary>
         /// <remarks>
-        /// FaceTrackingModel is loaded from the absolute path directory.\n
-        /// Models has been saved by <see cref="Save()"/> function can be loaded with this function
+        /// Models has been saved by <see cref="Save()"/> can be loaded.
         /// </remarks>
-        /// <param name="fileName">Name of path/file to load the model</param>
+        /// <param name="modelPath">Path to the model to load.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception>
+        /// <exception cref="System.IO.FileNotFoundException"><paramref name="modelPath"/> is invalid.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     The feature is not supported.\n
+        ///     - or -\n
+        ///     <paramref name="modelPath"/> is not supported format.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception>
         /// <seealso cref="Save()"/>
-        /// <seealso cref="Prepare()"/>
-        /// <code>
-        /// 
-        /// </code>
-        public FaceTrackingModel(string fileName)
+        public FaceTrackingModel(string modelPath)
         {
-            int ret = Interop.MediaVision.FaceTrackingModel.Load(fileName, out _trackingModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to load FaceTrackingModel from file.");
+            if (modelPath == null)
+            {
+                throw new ArgumentNullException(nameof(modelPath));
+            }
+            InteropModel.Load(modelPath, out _handle).Validate("Failed to load FaceTrackingModel from file.");
         }
 
-        /// <summary>
-        /// Destructor of the FaceTrackingModel class.
-        /// </summary>
         ~FaceTrackingModel()
         {
             Dispose(false);
         }
 
+        private MediaVisionError InvokePrepare(MediaVisionSource source, Quadrangle region)
+        {
+            if (region != null)
+            {
+                var quad = region.ToMarshalable();
+                return InteropModel.Prepare(Handle, IntPtr.Zero, source.Handle, ref quad);
+            }
+
+            return InteropModel.Prepare(Handle, IntPtr.Zero, source.Handle, IntPtr.Zero);
+        }
+
         /// <summary>
-        /// Calls this function to initialize tracking model by the location of the face to be tracked.
+        /// Initializes tracking model by the location of the face to be tracked.
+        ///
+        /// It is usually called once after tracking model is created and each time before tracking
+        /// is started for the new sequence of sources which is not the direct continuation of
+        /// the sequence for which tracking has been performed before. But it is allowed to call it
+        /// between tracking sessions to allow Media Vision start to track more accurately.
         /// </summary>
-        /// <param name="config">The configuration of engine will be used for model preparing. If NULL, then default settings will be used.</param>
-        /// <param name="source">The source where face location is specified. Usually it is the first frame of the video or the first image in the continuous image sequence planned to be used for tracking</param>
-        /// <param name="location">The quadrangle-shaped location determining position of the face to be tracked on the source. If NULL, then tracking model will try to find previously tracked face by itself. Don't set NULL when called first time for the tracking model.</param>
-        public void Prepare(FaceEngineConfiguration config, MediaVisionSource source, Quadrangle location = null)
+        /// <remarks>
+        /// <paramref name="region"/> needs to be the position of the face to be tracked when called first time for the tracking model.
+        /// </remarks>
+        /// <param name="source">The source where face location is specified.
+        ///     Usually it is the first frame of the video or the first image in the continuous
+        ///     image sequence planned to be used for tracking.</param>
+        /// <param name="region">The region determining position of the face to be tracked on the source.
+        ///     If null, then tracking model will try to find previously tracked face by itself.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ArgumentException"><paramref name="region"/> has invalid points.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="FaceTrackingModel"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already bean disposed of.
+        /// </exception>
+        public void Prepare(MediaVisionSource source, Quadrangle region)
         {
             if (source == null)
             {
-                throw new ArgumentException("Invalid source");
+                throw new ArgumentNullException(nameof(source));
             }
 
-            IntPtr ptr = IntPtr.Zero;
-            if (location != null)
-            {
-                Interop.MediaVision.Quadrangle quadrangle = new Interop.MediaVision.Quadrangle()
-                {
-                    x1 = location.Points[0].X, y1 = location.Points[0].Y,
-                    x2 = location.Points[1].X, y2 = location.Points[1].Y,
-                    x3 = location.Points[2].X, y3 = location.Points[2].Y,
-                    x4 = location.Points[3].X, y4 = location.Points[3].Y
-                };
-                ptr = Marshal.AllocHGlobal(Marshal.SizeOf(quadrangle));
-                Marshal.StructureToPtr(quadrangle, ptr, false);
-            }
-
-            int ret = Interop.MediaVision.FaceTrackingModel.Prepare(_trackingModelHandle,
-                                                                    (config != null) ? config._engineHandle : IntPtr.Zero,
-                                                                    source._sourceHandle, ptr);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to prepare tracking model.");
+            InvokePrepare(source, region).Validate("Failed to prepare tracking model.");
         }
 
         /// <summary>
-        /// Calls this method to save tracking model to the file.
+        /// Saves the tracking model to the file.
         /// </summary>
-        /// <remarks>
-        /// TrackingModel is saved to the absolute path directory.
-        /// </remarks>
-        /// <param name="fileName">Name of the path/file to save the model</param>
-        public void Save(string fileName)
+        /// <param name="path">Path to the file to save the model.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception>
+        /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception>
+        public void Save(string path)
         {
-            if (string.IsNullOrEmpty(fileName))
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
+
+            var ret = InteropModel.Save(path, Handle);
+
+            if (ret == MediaVisionError.InvalidPath)
             {
-                throw new ArgumentException("Invalid file name");
+                throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist.");
             }
 
-            int ret = Interop.MediaVision.FaceTrackingModel.Save(fileName, _trackingModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to save tracking model to file");
+            ret.Validate("Failed to save tracking model to file");
         }
 
         public void Dispose()
@@ -131,13 +149,20 @@ namespace Tizen.Multimedia
                 return;
             }
 
-            if (disposing)
+            InteropModel.Destroy(_handle);
+            _disposed = true;
+        }
+
+        internal IntPtr Handle
+        {
+            get
             {
-                // Free managed objects
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(nameof(FaceTrackingModel));
+                }
+                return _handle;
             }
-
-            Interop.MediaVision.FaceTrackingModel.Destroy(_trackingModelHandle);
-            _disposed = true;
         }
     }
 }
index 6e88303..f7b4a74 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents result of face tracking operation.
+    /// Represents result of face tracking operation.
     /// </summary>
     public class FaceTrackingResult
     {
-        internal FaceTrackingResult()
+        internal FaceTrackingResult(bool success, double confidence, Quadrangle region)
         {
+            Success = success;
+            Confidence = confidence;
+            Region = region;
         }
 
         /// <summary>
-        /// Gets the quadrangle-shaped location which determines new position of the tracked face on the source.
+        /// Gets the value indicating the recognition is successful.
         /// </summary>
-        public Quadrangle Location { get; internal set; }
+        public bool Success { get; }
+
+        /// <summary>
+        /// Gets the region which determines new position of the tracked face on the source.
+        /// </summary>
+        public Quadrangle Region { get; }
 
         /// <summary>
         /// The confidence of the tracking_model that new location of the face was determined correctly
-        /// (value from 0.0 to 1.0). If no location was determined during last track iteration, then value is 0.0
+        /// (value from 0.0 to 1.0). If no location was determined during last track iteration, then value is 0.0.
         /// </summary>
-        public double Confidence { get; internal set; }
+        public double Confidence { get; }
     }
 }
index aab257c..97dd987 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for expression types can be determined for faces.
+    /// Specifies the expression types for faces.
     /// </summary>
     public enum FacialExpression
     {
         /// <summary>
-        /// Unknown face expression
+        /// Unknown face expression.
         /// </summary>
         Unknown,
+
         /// <summary>
-        /// Face expression is neutral
+        /// Face expression is neutral.
         /// </summary>
         Neutral,
+
         /// <summary>
-        /// Face expression is smiling
+        /// Face expression is smiling.
         /// </summary>
         Smile,
+
         /// <summary>
-        /// Face expression is sadness
+        /// Face expression is sadness.
         /// </summary>
         Sadness,
+
         /// <summary>
-        /// Face expression is surprise
+        /// Face expression is surprise.
         /// </summary>
         Surprise,
+
         /// <summary>
-        /// Face expression is anger
+        /// Face expression is anger.
         /// </summary>
         Anger,
+
         /// <summary>
-        /// Face expression is fear
+        /// Face expression is fear.
         /// </summary>
         Fear,
+
         /// <summary>
-        /// Face expression is disgust
+        /// Face expression is disgust.
         /// </summary>
         Disgust
     }
diff --git a/src/Tizen.Multimedia/MediaVision/Image.cs b/src/Tizen.Multimedia/MediaVision/Image.cs
deleted file mode 100755 (executable)
index 56f4104..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-using System.Runtime.InteropServices;
-using Tizen.Multimedia;
-using static Interop.MediaVision;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents an interface for Image objects.
-    /// </summary>
-    public class Image : IDisposable
-    {
-        internal IntPtr _imageObjectHandle = IntPtr.Zero;
-        private bool _disposed = false;
-
-        /// <summary>
-        /// Constructor of Image object class
-        /// </summary>
-        public Image()
-        {
-            int ret = Interop.MediaVision.Image.Create(out _imageObjectHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to create image object");
-        }
-
-        /// <summary>
-        /// Constructor of image object class
-        /// </summary>
-        /// <param name="fileName">Name of path/file to load the image object</param>
-        public Image(string fileName)
-        {
-            int ret = Interop.MediaVision.Image.Load(fileName, out _imageObjectHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to load image object from file");
-        }
-
-        /// <summary>
-        /// Destructor of ImageObject
-        /// </summary>
-        ~Image()
-        {
-            Dispose(false);
-        }
-
-        /// <summary>
-        /// Sets and gets a label for the image object
-        /// </summary>
-        public int Label
-        {
-            get
-            {
-                int label = 0;
-                MediaVisionError ret = (MediaVisionError)Interop.MediaVision.Image.GetLabel(_imageObjectHandle, out label);
-                if (ret != MediaVisionError.None)
-                {
-                    Tizen.Log.Error(MediaVisionLog.Tag, "Failed to get label");
-                }
-
-                return label;
-            }
-
-            set
-            {
-                int ret = Interop.MediaVision.Image.SetLabel(_imageObjectHandle, value);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to set label");
-            }
-        }
-
-        /// <summary>
-        /// Gets a value that determines how well an image object can be recognized.
-        /// </summary>
-        public double RecognitionRate
-        {
-            get
-            {
-                double rate = 0;
-                MediaVisionError ret = (MediaVisionError)Interop.MediaVision.Image.GetRecognitionRate(_imageObjectHandle, out rate);
-                if (ret != MediaVisionError.None)
-                {
-                    Tizen.Log.Error(MediaVisionLog.Tag, "Failed to get recognition rate, error : " + ret);
-                }
-
-                return rate;
-            }
-        }
-
-        /// <summary>
-        /// Fills the image object.\n
-        /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location.
-        /// </summary>
-        /// <param name="source">The source image where image object is depicted</param>
-        /// <param name="config">The configuration of engine which will be used for extract recognition data from source. If NULL, then default settings will be used.</param>
-        /// <param name="location">Location of the image object on the source image, or NULL if the object is shown in full</param>
-        public void Fill(MediaVisionSource source, ImageEngineConfiguration config = null, Rectangle location = null)
-        {
-            if (source == null)
-            {
-                throw new ArgumentException("Inalid source");
-            }
-
-            IntPtr locationPtr = IntPtr.Zero;
-            if (location != null)
-            {
-                Interop.MediaVision.Rectangle rectangle = new Interop.MediaVision.Rectangle()
-                {
-                    width = location.Width,
-                    height = location.Height,
-                    x = location.Point.X,
-                    y = location.Point.Y
-                };
-                locationPtr = Marshal.AllocHGlobal(Marshal.SizeOf(rectangle));
-                Marshal.StructureToPtr(rectangle, locationPtr, false);
-            }
-
-            int ret = Interop.MediaVision.Image.Fill(_imageObjectHandle,
-                                                    (config != null) ? config._engineHandle : IntPtr.Zero,
-                                                    source._sourceHandle, locationPtr);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to fill the image object");
-        }
-
-        /// <summary>
-        /// Saves the image object.
-        /// </summary>
-        /// <param name="fileName">Name of the file to path/save the image object</param>
-        public void Save(string fileName)
-        {
-            if (string.IsNullOrEmpty(fileName))
-            {
-                throw new ArgumentException("Inalid file name");
-            }
-
-            int ret = Interop.MediaVision.Image.Save(fileName, _imageObjectHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to save the image object");
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if (_disposed)
-            {
-                return;
-            }
-
-            if (disposing)
-            {
-                // Free managed objects
-            }
-
-            Interop.MediaVision.Image.Destroy(_imageObjectHandle);
-            _disposed = true;
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/ImageEngineConfiguration.cs b/src/Tizen.Multimedia/MediaVision/ImageEngineConfiguration.cs
deleted file mode 100755 (executable)
index e0c058f..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents concrete EngineConfig for image recognition and tracking
-    /// </summary>
-    public class ImageEngineConfiguration : EngineConfiguration
-    {
-        // List of predefined keys
-        private const string _imageRecognitionObjectScaleFactorKey = "MV_IMAGE_RECOGNITION_OBJECT_SCALE_FACTOR";
-        private const string _imageRecognitionObjectMaxKeypointsKey = "MV_IMAGE_RECOGNITION_OBJECT_MAX_KEYPOINTS_NUM";
-        private const string _imageRecognitionSceneScaleFactorKey = "MV_IMAGE_RECOGNITION_SCENE_SCALE_FACTOR";
-        private const string _imageRecognitionSceneMaxKeypointsKey = "MV_IMAGE_RECOGNITION_SCENE_MAX_KEYPOINTS_NUM";
-        private const string _imageRecognitionMinKeypointsMatchKey = "MV_IMAGE_RECOGNITION_MIN_MATCH_NUM";
-        private const string _imageRecognitionReqMatchPartKey = "MV_IMAGE_RECOGNITION_REQ_MATCH_PART";
-        private const string _imageRecognitionTolerantPartMatchingErrorKey = "MV_IMAGE_RECOGNITION_TOLERANT_MATCH_PART_ERR";
-        private const string _imageTrackingHistoryAmountKey = "MV_IMAGE_TRACKING_HISTORY_AMOUNT";
-        private const string _imageTrackingExpectedOffsetKey = "MV_IMAGE_TRACKING_EXPECTED_OFFSET";
-        private const string _imageTrackingUseStabilizationKey = "MV_IMAGE_TRACKING_USE_STABLIZATION";
-        private const string _imageTrackingStabilizationTolerantShiftKey = "MV_IMAGE_TRACKING_STABLIZATION_TOLERANT_SHIFT";
-        private const string _imageTrackingStabilizationSpeedKey = "MV_IMAGE_TRACKING_STABLIZATION_SPEED";
-        private const string _imageTrackingStabilizationAccelarationKey = "MV_IMAGE_TRACKING_STABLIZATION_ACCELERATION";
-
-        // Values are cached below to prevent interop calls for get operation
-        private double _imageRecognitionObjectScaleFactorValue = 1.2;
-        private int _imageRecognitionObjectMaxKeypointsValue = 1000;
-        private double _imageRecognitionSceneScaleFactorValue = 1.2;
-        private int _imageRecognitionSceneMaxKeypointsValue = 5000;
-        private int _imageRecognitionMinKeypointsMatchValue = 30;
-        private double _imageRecognitionReqMatchPartValue = 0.05;
-        private double _imageRecognitionTolerantPartMatchingErrorValue = 0.1;
-        private int _imageTrackingHistoryAmountValue = 3;
-        private double _imageTrackingExpectedOffsetValue = 0;
-        private bool _imageTrackingUseStabilizationValue = true;
-        private double _imageTrackingStabilizationTolerantShiftValue = 0.00006;
-        private double _imageTrackingStabilizationSpeedValue = 0.3;
-        private double _imageTrackingStabilizationAccelarationValue = 0.1;
-
-        /// <summary>
-        /// The default constructor of ImageEngineConfiguration class
-        /// </summary>
-        /// <code>
-        /// 
-        /// </code>
-        public ImageEngineConfiguration()
-            : base()
-        {
-            ObjectScaleFactor = _imageRecognitionObjectScaleFactorValue;
-            ObjectMaxKeyPoints = _imageRecognitionObjectMaxKeypointsValue;
-            SceneScaleFactor = _imageRecognitionSceneScaleFactorValue;
-            SceneMaxKeyPoints = _imageRecognitionSceneMaxKeypointsValue;
-            MinKeyPointsMatches = _imageRecognitionMinKeypointsMatchValue;
-            RequiredMatchingPart = _imageRecognitionReqMatchPartValue;
-            TolerantPartMatchingError = _imageRecognitionTolerantPartMatchingErrorValue;
-            TrackingHistoryAmount = _imageTrackingHistoryAmountValue;
-            ExpectedTrackingOffset = _imageTrackingExpectedOffsetValue;
-            UseTrackingStabilization = _imageTrackingUseStabilizationValue;
-            TrackingStabilizationTolerantShift = _imageTrackingStabilizationTolerantShiftValue;
-            TrackingStabilizationSpeed = _imageTrackingStabilizationSpeedValue;
-            TrackingStabilizationAccelaration = _imageTrackingStabilizationAccelarationValue;
-        }
-
-        /// <summary>
-        /// Sets and gets the image to be recognized scale factor attribute of the engine configuration.\n
-        /// The value of the factor will be used for resizing of the images (objects) for recognition.
-        /// Scale factor is the double value and the defalut is 1.2
-        /// </summary>
-        public double ObjectScaleFactor
-        {
-            get
-            {
-                return _imageRecognitionObjectScaleFactorValue;
-            }
-
-            set
-            {
-                Add<double>(_imageRecognitionObjectScaleFactorKey, value);
-                _imageRecognitionObjectScaleFactorValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the maximum keypoints should be detected on the image attribute of the engine configuration.\n
-        /// The maximal number of keypoints can be selected on the image object to calculate descriptors.
-        /// This keypoints will be used for image (object) recognition and has to be specified as integer number and the defalut is 1000.
-        /// </summary>
-        public int ObjectMaxKeyPoints
-        {
-            get
-            {
-                return _imageRecognitionObjectMaxKeypointsValue;
-            }
-
-            set
-            {
-                Add<int>(_imageRecognitionObjectMaxKeypointsKey, (int)value);
-                _imageRecognitionObjectMaxKeypointsValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the scene scale factor attribute of the engine configuration.\n
-        /// The value of the factor will be used for resizing of the scene including the images (objects) for recognition.
-        /// Scale factor is the double value and the defalut is 1.2
-        /// </summary>
-        public double SceneScaleFactor
-        {
-            get
-            {
-                return _imageRecognitionSceneScaleFactorValue;
-            }
-
-            set
-            {
-                Add<double>(_imageRecognitionSceneScaleFactorKey, value);
-                _imageRecognitionSceneScaleFactorValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets set the maximum keypoints should be detected on the scene attribute of the engine configuration.\n
-        /// The maximal number of keypoints can be selected on the scene including the images (objects) to calculate descriptors.
-        /// This keypoints will be used for image recognition and has to be specified as unsigned integer and the defalut is 5000.
-        /// </summary>
-        public int SceneMaxKeyPoints
-        {
-            get
-            {
-                return _imageRecognitionSceneMaxKeypointsValue;
-            }
-
-            set
-            {
-                Add<int>(_imageRecognitionSceneMaxKeypointsKey, value);
-                _imageRecognitionSceneMaxKeypointsValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the minimum number of keypoints matches required for recognition attribute of the engine configuration.\n
-        /// The minimal number of keypoints should be matched between an image and a scene.
-        /// It will be taken into account for image objects recognition. Value is unsigned integer and the defalut is 30.
-        /// </summary>
-        public int MinKeyPointsMatches
-        {
-            get
-            {
-                return _imageRecognitionMinKeypointsMatchValue;
-            }
-
-            set
-            {
-                Add<int>(_imageRecognitionMinKeypointsMatchKey, value);
-                _imageRecognitionMinKeypointsMatchValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the required matching part for the image recognition attribute of the engine configuration.\n
-        /// To recognize occluded or hidden an image by other images, required relative part of the matches in respect to the total
-        /// amount of matching keypoints required for image recognition. Too low value will result in unsustainable behavior,
-        /// but effect of object overlapping will be reduced. Value can be from 0 to 1 and the defalut is 0.05.
-        /// </summary>
-        public double RequiredMatchingPart
-        {
-            get
-            {
-                return _imageRecognitionReqMatchPartValue;
-            }
-
-            set
-            {
-                if (value < 0 || value > 1)
-                {
-                    throw new ArgumentException("Invalid value");
-                }
-
-                Add<double>(_imageRecognitionReqMatchPartKey, value);
-                _imageRecognitionReqMatchPartValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the part matching error for the image recognition attribute of the engine configuration.\n
-        /// Allowable error of matches number. Value can be from 0 to 1 and the defalut is 0.1
-        /// </summary>
-        public double TolerantPartMatchingError
-        {
-            get
-            {
-                return _imageRecognitionTolerantPartMatchingErrorValue;
-            }
-
-            set
-            {
-                if (value < 0 || value > 1)
-                {
-                    throw new ArgumentException("Invalid value");
-                }
-
-                Add<double>(_imageRecognitionTolerantPartMatchingErrorKey, value);
-                _imageRecognitionTolerantPartMatchingErrorValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the number of recognition results in the tracking history attribute of the engine configuration.\n
-        /// Number of previous recognition results, which will influence the stabilization. Value is unsigned integer and the defalut is 3.
-        /// </summary>
-        public int TrackingHistoryAmount
-        {
-            get
-            {
-                return _imageTrackingHistoryAmountValue;
-            }
-
-            set
-            {
-                Add<int>(_imageTrackingHistoryAmountKey, value);
-                _imageTrackingHistoryAmountValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the expected tracking offset attribute of the engine configuration.\n
-        /// Relative offset value, for which the object offset is expected (relative to the object size in the current frame).
-        /// Value is a double and the defalut is 0.
-        /// </summary>
-        public double ExpectedTrackingOffset
-        {
-            get
-            {
-                return _imageTrackingExpectedOffsetValue;
-            }
-
-            set
-            {
-                Add<double>(_imageTrackingExpectedOffsetKey, value);
-                _imageTrackingExpectedOffsetValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the acceleration of the tracking stabilization attribute of the engine configuration.\n
-        /// Acceleration will be used for image stabilization (relative to the distance from current location to stabilized location).
-        /// Value is double from 0 to 1 and the defalut is 0.1.
-        /// </summary>
-        public double TrackingStabilizationAccelaration
-        {
-            get
-            {
-                return _imageTrackingStabilizationAccelarationValue;
-            }
-
-            set
-            {
-                if (value < 0 || value > 1)
-                {
-                    throw new ArgumentException("Invalid value");
-                }
-
-                Add<double>(_imageTrackingStabilizationAccelarationKey, value);
-                _imageTrackingStabilizationAccelarationValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the speed of the tracking stabilization attribute of the engine configuration.\n
-        /// Start speed will be used for image stabilization. Value is a double and the defalut is 0.3.
-        /// </summary>
-        public double TrackingStabilizationSpeed
-        {
-            get
-            {
-                return _imageTrackingStabilizationSpeedValue;
-            }
-
-            set
-            {
-                Add<double>(_imageTrackingStabilizationSpeedKey, value);
-                _imageTrackingStabilizationSpeedValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets the relative tolerant shift for the tracking stabilization attribute of the engine configuration.\n
-        /// It is component of tolerant shift which will be ignored by stabilization process.
-        /// </summary>
-        public double TrackingStabilizationTolerantShift
-        {
-            get
-            {
-                return _imageTrackingStabilizationTolerantShiftValue;
-            }
-
-            set
-            {
-                Add<double>(_imageTrackingStabilizationTolerantShiftKey, value);
-                _imageTrackingStabilizationTolerantShiftValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Enables/disables the contour stabilization during tracking process. Default value is true.
-        /// </summary>
-        public bool UseTrackingStabilization
-        {
-            get
-            {
-                return _imageTrackingUseStabilizationValue;
-            }
-
-            set
-            {
-                Add<bool>(_imageTrackingUseStabilizationKey, value);
-                _imageTrackingUseStabilizationValue = value;
-            }
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/ImageFillConfiguration.cs b/src/Tizen.Multimedia/MediaVision/ImageFillConfiguration.cs
new file mode 100644 (file)
index 0000000..27d1c86
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of fill operations of <see cref="ImageObject"/> instances.
+    /// </summary>
+    public class ImageFillConfiguration : EngineConfiguration
+    {
+        private const string KeyScaleFactor = "MV_IMAGE_RECOGNITION_OBJECT_SCALE_FACTOR";
+        private const string KeyMaxKeypoints = "MV_IMAGE_RECOGNITION_OBJECT_MAX_KEYPOINTS_NUM";
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="ObjectScaleFactor"/>.
+        /// </summary>
+        public static readonly double DefaultScaleFactor = 1.2;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="ObjectMaxKeyPoints"/>.
+        /// </summary>
+        public static readonly int DefaultMaxKeypoints = 1000;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ImageFillConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="System.NotSupportedException">The feature is not supported.</exception>
+        public ImageFillConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the scale factor the image to be recognized.\n
+        /// The value of the factor will be used for resizing of the images (objects) for recognition.
+        /// The default value is 1.2.
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageFillConfiguration"/> already has been disposed of.</exception>
+        public double ObjectScaleFactor
+        {
+            get
+            {
+                return GetDouble(KeyScaleFactor);
+            }
+            set
+            {
+                Set(KeyScaleFactor, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the maximum key points should be detected on the image.\n
+        /// The maximal number of key points can be selected on the image object to calculate descriptors.
+        /// This key points will be used for image (object) recognition and has to be specified as integer number.
+        /// The default value is 1000.
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageFillConfiguration"/> already has been disposed of.</exception>
+        public int ObjectMaxKeyPoints
+        {
+            get
+            {
+                return GetInt(KeyMaxKeypoints);
+            }
+            set
+            {
+                Set(KeyMaxKeypoints, value);
+            }
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/ImageObject.cs b/src/Tizen.Multimedia/MediaVision/ImageObject.cs
new file mode 100644 (file)
index 0000000..eedcbba
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.IO;
+using InteropImage = Interop.MediaVision.Image;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents an image object.
+    /// </summary>
+    public class ImageObject : IDisposable
+    {
+        private IntPtr _handle = IntPtr.Zero;
+        private bool _disposed = false;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ImageObject"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public ImageObject()
+        {
+            InteropImage.Create(out _handle).Validate("Failed to create image object");
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ImageObject"/> class from the specified file.
+        /// </summary>
+        /// <remarks>
+        /// ImageObject has been saved by <see cref="Save()"/> can be loaded.
+        /// </remarks>
+        /// <param name="path">Path to the image object to load.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="FileNotFoundException"><paramref name="path"/> is invalid.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     The feature is not supported.\n
+        ///     - or -\n
+        ///     <paramref name="path"/> is not supported file.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception>
+        /// <seealso cref="Save(string)"/>
+        public ImageObject(string path)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
+            InteropImage.Load(path, out _handle).Validate("Failed to load image object from file");
+        }
+
+        ~ImageObject()
+        {
+            Dispose(false);
+        }
+
+        /// <summary>
+        /// Gets a value that determines how well an image object can be recognized.
+        /// </summary>
+        /// <remarks>
+        /// If recognition rate is too low, try to use another image or change some configuration parameters
+        /// and fill the image object again.
+        /// </remarks>
+        /// <value>
+        /// Recognition rate determines how well an image object can be recognized. This value can be from 0 to 1.
+        /// If the recognition rate is 0 object can not be recognized and the bigger it is the more likely to recognize the object.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageObject"/> has already been disposed of.</exception>
+        /// <seealso cref="ImageFillConfiguration"/>
+        /// <seealso cref="Fill(MediaVisionSource, ImageFillConfiguration, Rectangle?)"/>
+        public double RecognitionRate
+        {
+            get
+            {
+                double rate = 0;
+                InteropImage.GetRecognitionRate(Handle, out rate).Validate("Failed to get recognition rate");
+                return rate;
+            }
+        }
+
+        #region Methods
+        /// <summary>
+        /// Gets the label for the image object.
+        /// </summary>
+        /// <returns>
+        /// The label value; or null if the <see cref="ImageObject"/> has no label.
+        /// </returns>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageObject"/> has already been disposed of.</exception>
+        /// <seealso cref="SetLabel(int)"/>
+        public int? GetLabel()
+        {
+            int label = 0;
+            var ret = InteropImage.GetLabel(Handle, out label);
+
+            if (ret == MediaVisionError.NoData)
+            {
+                return null;
+            }
+
+            ret.Validate("Failed to get label");
+            return label;
+        }
+
+        /// <summary>
+        /// Sets the label for the <see cref="ImageObject"/>.
+        /// </summary>
+        /// <seealso cref="GetLabel"/>
+        public void SetLabel(int label)
+        {
+            InteropImage.SetLabel(Handle, label).Validate("Failed to set label");
+        }
+
+        /// <summary>
+        /// Fills the image object.\n
+        /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location.
+        /// </summary>
+        /// <param name="source">The source image where image object is depicted.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="ImageObject"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already been disposed of.
+        /// </exception>
+        public void Fill(MediaVisionSource source)
+        {
+            InvokeFill(source, null, null);
+        }
+
+        /// <summary>
+        /// Fills the image object.\n
+        /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location.
+        /// </summary>
+        /// <param name="source">The source image where image object is depicted.</param>
+        /// <param name="config">The configuration used for extract recognition data from source. This value can be null.</param>
+        /// <param name="area">Location of the image object on the source image, or NULL if the object is shown in full</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="ImageObject"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception
+        public void Fill(MediaVisionSource source, ImageFillConfiguration config)
+        {
+            InvokeFill(source, config, null);
+        }
+
+        /// <summary>
+        /// Fills the image object.\n
+        /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location.
+        /// </summary>
+        /// <param name="source">The source image where image object is depicted.</param>
+        /// <param name="rect">Rectangular bound of the image object on the source image.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="ImageObject"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already been disposed of.\n
+        /// </exception
+        public void Fill(MediaVisionSource source, Rectangle rect)
+        {
+            InvokeFill(source, null, rect);
+        }
+
+        /// <summary>
+        /// Fills the image object.\n
+        /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location.
+        /// </summary>
+        /// <param name="source">The source image where image object is depicted.</param>
+        /// <param name="config">The configuration used for extract recognition data from source. This value can be null.</param>
+        /// <param name="rect">Rectangular bound of the image object on the source image.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="ImageObject"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception
+        public void Fill(MediaVisionSource source, ImageFillConfiguration config, Rectangle rect)
+        {
+            InvokeFill(source, config, rect);
+        }
+
+        private MediaVisionError InvokeFill(IntPtr source, IntPtr config, Rectangle? area)
+        {
+            if (area == null)
+            {
+                return InteropImage.Fill(Handle, config, source, IntPtr.Zero);
+            }
+
+            var rect = area.Value.ToMarshalable();
+
+            return InteropImage.Fill(Handle, config, source, ref rect);
+        }
+
+        /// <summary>
+        /// Fills the image object.\n
+        /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location.
+        /// </summary>
+        /// <param name="source">The source image where image object is depicted.</param>
+        /// <param name="config">The configuration used for extract recognition data from source. This value can be null.</param>
+        /// <param name="area">Location of the image object on the source image, or NULL if the object is shown in full</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="ImageObject"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="source"/> has already been disposed of.
+        /// </exception
+        private void InvokeFill(MediaVisionSource source, ImageFillConfiguration config, Rectangle? area)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException(nameof(source));
+            }
+
+            InvokeFill(source.Handle, EngineConfiguration.GetHandle(config), area).
+                Validate("Failed to fill the image object");
+        }
+
+        /// <summary>
+        /// Saves the image object.
+        /// </summary>
+        /// <param name="path">Path to the file to save the model.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception>
+        /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception>
+        public void Save(string path)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
+
+            var ret = InteropImage.Save(path, Handle);
+
+            if (ret == MediaVisionError.InvalidPath)
+            {
+                throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist.");
+            }
+
+            ret.Validate("Failed to save the image object");
+        }
+        #endregion
+
+        #region IDisposable-support
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_disposed)
+            {
+                return;
+            }
+
+            InteropImage.Destroy(_handle);
+            _disposed = true;
+        }
+
+        internal IntPtr Handle
+        {
+            get
+            {
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(nameof(ImageObject));
+                }
+                return _handle;
+            }
+        }
+        #endregion
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/ImageRecognitionConfiguration.cs b/src/Tizen.Multimedia/MediaVision/ImageRecognitionConfiguration.cs
new file mode 100644 (file)
index 0000000..687e494
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="ImageRecognizer"/>.
+    /// </summary>
+    public class ImageRecognitionConfiguration : EngineConfiguration
+    {
+        private const string KeySceneScaleFactor = "MV_IMAGE_RECOGNITION_SCENE_SCALE_FACTOR";
+        private const string KeySceneMaxKeypoints = "MV_IMAGE_RECOGNITION_SCENE_MAX_KEYPOINTS_NUM";
+
+        private const string KeyMinKeypointsMatch = "MV_IMAGE_RECOGNITION_MIN_MATCH_NUM";
+        private const string KeyReqMatchPartKey = "MV_IMAGE_RECOGNITION_REQ_MATCH_PART";
+        private const string KeyTolerantPartMatchingError = "MV_IMAGE_RECOGNITION_TOLERANT_MATCH_PART_ERR";
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="KeySceneScaleFactor"/>.
+        /// </summary>
+        public static readonly double DefaultSceneScaleFactor = 1.2;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="SceneMaxKeyPoints"/>.
+        /// </summary>
+        public static readonly int DefaultSceneMaxKeypoints = 5000;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="MinKeyPointMatches"/>.
+        /// </summary>
+        public static readonly int DefaultMinKeyPointMatches = 30;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="RequiredMatchingPart"/>.
+        /// </summary>
+        public static readonly double DefaultRequiredMatchPart = 0.05;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="TolerantPartMatchError"/>.
+        /// </summary>
+        public static readonly double DefaultTolerantPartMatchError = 0.1;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ImageRecognitionConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public ImageRecognitionConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the scene scale factor.
+        /// </summary>
+        /// <value>
+        /// The value indicating the factor will be used for resizing of the scene including the images (objects) for recognition.
+        /// The default is 1.2.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception>
+        public double SceneScaleFactor
+        {
+            get
+            {
+                return GetDouble(KeySceneScaleFactor);
+            }
+            set
+            {
+                Set(KeySceneScaleFactor, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the maximum key points that should be detected on the scene.
+        /// The maximal number of key points can be selected on the scene including the images (objects) to calculate descriptors.
+        /// </summary>
+        /// <value>
+        /// The maximal key points for image recognition.
+        /// The default is 5000.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        public int SceneMaxKeyPoints
+        {
+            get
+            {
+                return GetInt(KeySceneMaxKeypoints);
+            }
+            set
+            {
+                if (value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(SceneMaxKeyPoints), value,
+                        $"{nameof(SceneMaxKeyPoints)} can't be less than zero.");
+                }
+                Set(KeySceneMaxKeypoints, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the minimum number of key points matches required for recognition.
+        /// </summary>
+        /// <value>
+        /// The minimal number of key points should be matched between an image and a scene for image objects recognition.
+        /// The default is 30.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        public int MinKeyPointMatches
+        {
+            get
+            {
+                return GetInt(KeyMinKeypointsMatch);
+            }
+            set
+            {
+                if (value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(MinKeyPointMatches), value,
+                        $"{nameof(MinKeyPointMatches)} can't be less than zero.");
+                }
+                Set(KeyMinKeypointsMatch, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the required matching part for the image recognition.
+        /// To recognize occluded or hidden an image by other images, required relative part of the matches in respect to the total
+        /// amount of matching keypoints required for image recognition. Too low value will result in unsustainable behavior,
+        /// but effect of object overlapping will be reduced.
+        /// </summary>
+        /// <value>
+        /// The value indicating required relative part of the matches; can be from 0 to 1, inclusive.
+        /// The default is 0.05.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="value"/> is less than zero.\n
+        ///     - or -\n
+        ///     <paramref name="value"/> is greater than one.
+        /// </exception>
+        public double RequiredMatchingPart
+        {
+            get
+            {
+                return GetDouble(KeyReqMatchPartKey);
+            }
+            set
+            {
+                if (value < 0 || value > 1)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value, "Valid range is 0 to 1 inclusive,");
+                }
+                Set(KeyReqMatchPartKey, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the part matching error for the image recognition.\n
+        /// Allowable error of matches number.
+        /// </summary>
+        /// <value>
+        /// The value indicating allowable error of matches; can be from 0 to 1, inclusive.
+        /// The default is 0.1.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="value"/> is less than zero.\n
+        ///     - or -\n
+        ///     <paramref name="value"/> is greater than one.
+        /// </exception>
+        public double TolerantPartMatchError
+        {
+            get
+            {
+                return GetDouble(KeyTolerantPartMatchingError);
+            }
+            set
+            {
+                if (value < 0 || value > 1)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value, "Valid range is 0 to 1 inclusive.");
+                }
+
+                Set(KeyTolerantPartMatchingError, value);
+            }
+        }
+    }
+}
index 2bca0e7..5e4a9e4 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  * limitations under the License.
  */
 
-using System;
-using System.Collections.Generic;
-
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents result of image recognition.
+    /// Represents a result of RecognizeAsync operations of <see cref="ImageRecognizer"/>.
     /// </summary>
     public class ImageRecognitionResult
     {
-        internal ImageRecognitionResult()
+
+        internal ImageRecognitionResult(bool success, Quadrangle region)
         {
+            Success = success;
+            Region = region;
         }
 
         /// <summary>
-        /// The indexes of recognized image objects and their locations on the source image.
+        /// The region of recognized image object on the source image.
+        /// </summary>
+        public Quadrangle Region { get; }
+
+        /// <summary>
+        /// Gets the value indicating the recognition is successful.
         /// </summary>
-        public List<Tuple<int, Quadrangle>> Results { get; internal set; }
+        public bool Success { get; }
     }
 }
index 8a6042f..bf950ac 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -17,105 +17,138 @@ using System;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
-using static Interop.MediaVision;
+using InteropImage = Interop.MediaVision.Image;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents an interface for image recognition functionality.
+    /// Provides the ability to recognize images on image sources.
     /// </summary>
     public static class ImageRecognizer
     {
         /// <summary>
         /// Recognizes the given image objects on the source image.\n
-        /// Use this function to launch image recognition algorithm configured by @a config configuration.
         /// </summary>
-        /// <param name="source">The source image on which image objects will be recognized</param>
-        /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition</param>
-        /// <param name="config">The configuration of engine which will be used for recognition. If NULL, then default settings will be used.</param>
-        /// <returns>Returns ImageRecognitionResult asynchronously</returns>
-        public static async Task<ImageRecognitionResult> RecognizeAsync(MediaVisionSource source, Image[] imageObjects, ImageEngineConfiguration config = null)
+        /// <param name="source">The source image on which image objects will be recognized.</param>
+        /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition.</param>
+        /// <param name="config">The configuration of engine which will be used for recognition. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageObjects"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageObjects"/> contains null reference.
+        /// </exception>
+        /// <exception cref="ArgumentException"><paramref name="imageObjects"/> has no elements.(The length is zero.)</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception>
+        public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync(
+            MediaVisionSource source, ImageObject[] imageObjects)
         {
-            if (source == null || imageObjects.Length == 0)
+            return await RecognizeAsync(source, imageObjects, null);
+        }
+
+        /// <summary>
+        /// Recognizes the given image objects on the source image.\n
+        /// </summary>
+        /// <param name="source">The source image on which image objects will be recognized.</param>
+        /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition.</param>
+        /// <param name="config">The configuration used for recognition. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous recognition operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageObjects"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="imageObjects"/> contains null elements.
+        /// </exception>
+        /// <exception cref="ArgumentException"><paramref name="imageObjects"/> has no elements.(The length is zero.)</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync(MediaVisionSource source,
+            ImageObject[] imageObjects, ImageRecognitionConfiguration config)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException(nameof(source));
+            }
+            if (imageObjects == null)
+            {
+                throw new ArgumentNullException(nameof(imageObjects));
+            }
+            if (imageObjects.Length == 0)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new ArgumentException("No image object to recognize.", nameof(imageObjects));
             }
 
-            IntPtr[] ptrArray = new IntPtr[imageObjects.Length];
-            for (int i = 0; i < imageObjects.Length; i++)
+            var tcs = new TaskCompletionSource<IEnumerable<ImageRecognitionResult>>();
+
+            using (var cb = ObjectKeeper.Get(GetCallback(tcs)))
+            using (var imageHandles = ObjectKeeper.Get(GetHandles(imageObjects)))
             {
-                if (imageObjects[i] == null)
-                {
-                    throw new ArgumentException("Invalid parameter");
-                }
+                InteropImage.Recognize(source.Handle, imageHandles.Target, imageHandles.Target.Length,
+                    EngineConfiguration.GetHandle(config), cb.Target).
+                    Validate("Failed to perform image recognition.");
 
-                ptrArray[i] = imageObjects[i]._imageObjectHandle;
+                return await tcs.Task;
             }
+        }
+
+        private static ImageRecognitionResult[] CreateResults(IntPtr[] locations, uint numOfObjects)
+        {
+            ImageRecognitionResult[] results = new ImageRecognitionResult[numOfObjects];
 
-            int size = Marshal.SizeOf(typeof(IntPtr)) * ptrArray.Length;
-            IntPtr imageObjectsPtr = Marshal.AllocHGlobal(size);
+            for (int i = 0; i < numOfObjects; i++)
+            {
+                Quadrangle quadrangle = locations[i] != IntPtr.Zero ?
+                    Marshal.PtrToStructure<Interop.MediaVision.Quadrangle>(locations[i]).ToApiStruct() : null;
 
-            Marshal.Copy(ptrArray, 0, imageObjectsPtr, ptrArray.Length);
+                results[i] = new ImageRecognitionResult(locations[i] != IntPtr.Zero, quadrangle);
+            }
 
-            TaskCompletionSource<ImageRecognitionResult> tcsResult = new TaskCompletionSource<ImageRecognitionResult>();
+            return results;
+        }
 
-            // Define native callback
-            Interop.MediaVision.Image.MvImageRecognizedCallback imageRecognizedCb = (IntPtr sourceHandle, IntPtr engineCfgHandle, IntPtr imageObjectsHandle, IntPtr locationsPtr, uint numberOfObjects, IntPtr userData) =>
+        private static InteropImage.RecognizedCallback GetCallback(
+            TaskCompletionSource<IEnumerable<ImageRecognitionResult>> tcs)
+        {
+            return (IntPtr source, IntPtr engineConfig, IntPtr imageObjectHandles,
+                IntPtr[] locations, uint numOfObjects, IntPtr _) =>
             {
                 try
                 {
-                    List<Tuple<int, Quadrangle>> recognitionResults = new List<Tuple<int, Quadrangle>>();
-                    if (numberOfObjects > 0)
-                    {
-                        IntPtr[] imageLocationsPtr = new IntPtr[numberOfObjects];
-                        Marshal.Copy(locationsPtr, imageLocationsPtr, 0, (int)numberOfObjects);
-
-                        // Prepare list of locations and its indexes
-                        for (int i = 0; i < numberOfObjects; i++)
-                        {
-                            if (imageLocationsPtr[i] == null)
-                            {
-                                continue;
-                            }
-
-                            Interop.MediaVision.Quadrangle location = (Interop.MediaVision.Quadrangle)Marshal.PtrToStructure(imageLocationsPtr[i], typeof(Interop.MediaVision.Quadrangle));
-                            Quadrangle quadrangle = new Quadrangle()
-                            {
-                                Points = new Point[4]
-                                {
-                                new Point(location.x1, location.y1),
-                                new Point(location.x2, location.y2),
-                                new Point(location.x3, location.y3),
-                                new Point(location.x4, location.y4)
-                                }
-                            };
-                            Log.Info(MediaVisionLog.Tag, String.Format("Image recognized, Location : {0}", quadrangle.ToString()));
-                            recognitionResults.Add(Tuple.Create(i, quadrangle));
-                        }
-                    }
-
-                    ImageRecognitionResult result = new ImageRecognitionResult()
-                    {
-                        Results = recognitionResults
-                    };
-
-                    if (!tcsResult.TrySetResult(result))
+                    if (!tcs.TrySetResult(CreateResults(locations, numOfObjects)))
                     {
-                        Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                        tcsResult.TrySetException(new InvalidOperationException("Failed to set result"));
+                        Log.Info(MediaVisionLog.Tag, "Failed to set recognition result");
                     }
                 }
-                catch (Exception ex)
+                catch (Exception e)
                 {
-                    Log.Info(MediaVisionLog.Tag, "exception :" + ex.ToString());
-                    tcsResult.TrySetException(ex);
+                    MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle recognition result", e);
+                    tcs.TrySetException(e);
                 }
             };
+        }
 
-            int ret = Interop.MediaVision.Image.Recognize(source._sourceHandle, imageObjectsPtr, ptrArray.Length, (config != null) ? config._engineHandle : IntPtr.Zero, imageRecognizedCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to perform image recognition.");
+        private static IntPtr[] GetHandles(ImageObject[] imageObjects)
+        {
+            IntPtr[] imageHandles = new IntPtr[imageObjects.Length];
+            for (int i = 0; i < imageObjects.Length; i++)
+            {
+                if (imageObjects[i] == null)
+                {
+                    throw new ArgumentNullException($"{nameof(imageObjects)}[{i}]");
+                }
+
+                imageHandles[i] = imageObjects[i].Handle;
+            }
 
-            return await tcsResult.Task;
+            return imageHandles;
         }
     }
 }
index 9fd2505..d1f0a3e 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 using System;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
-using static Interop.MediaVision;
+using InteropImage = Interop.MediaVision.Image;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class contains the Media Vision image tracking API which performs tracking
-    /// on <see cref="MediaVisionSource"/> for <see cref="ImageTrackingModel"/>
+    /// Provides the ability to track images on image sources.
     /// </summary>
     public static class ImageTracker
     {
         /// <summary>
-        /// Tracks the given image tracking model on the current frame asynchronously.
+        /// Tracks the given image tracking model on the current frame.
         /// </summary>
-        /// <param name="source">The current image of sequence where image tracking model will be tracked</param>
-        /// <param name="trackingModel">The image tracking model which processed as target of tracking</param>
-        /// <param name="config">The configuration of engine which will be used for tracking. If NULL, then default settings will be used.</param>
-        /// <returns>Returns the image object location asynchronously</returns>
-        /// <code>
-        /// 
-        /// </code>
-        public static async Task<Quadrangle> TrackAsync(MediaVisionSource source, ImageTrackingModel trackingModel, ImageEngineConfiguration config = null)
+        /// <param name="source">The current image of sequence where image tracking model will be tracked.</param>
+        /// <param name="trackingModel">The image tracking model which processed as target of tracking.</param>
+        /// <returns>A task that represents the asynchronous tracking operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="trackingModel"/> is null.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="trackingModel"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="InvalidOperationException"><paramref name="trackingModel"/> has no target.</exception>
+        /// <seealso cref="ImageTrackingModel.SetTarget(ImageObject)"/>
+        public static async Task<Quadrangle> TrackAsync(MediaVisionSource source,
+            ImageTrackingModel trackingModel)
         {
-            if (source == null || trackingModel == null)
+            return await TrackAsync(source, trackingModel, null);
+        }
+
+        /// <summary>
+        /// Tracks the given image tracking model on the current frame and <see cref="ImageTrackingConfiguration"/>.
+        /// </summary>
+        /// <param name="source">The current image of sequence where image tracking model will be tracked.</param>
+        /// <param name="trackingModel">The image tracking model which processed as target of tracking.</param>
+        /// <param name="config">The configuration used for tracking. This value can be null.</param>
+        /// <returns>A task that represents the asynchronous tracking operation.</returns>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="trackingModel"/> is null.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     <paramref name="source"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="trackingModel"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="InvalidOperationException"><paramref name="trackingModel"/> has no target.</exception>
+        /// <seealso cref="ImageTrackingModel.SetTarget(ImageObject)"/>
+        public static async Task<Quadrangle> TrackAsync(MediaVisionSource source,
+            ImageTrackingModel trackingModel, ImageTrackingConfiguration config)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException(nameof(source));
+            }
+            if (trackingModel == null)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new ArgumentNullException(nameof(trackingModel));
             }
 
-            TaskCompletionSource<Quadrangle> tcsResult = new TaskCompletionSource<Quadrangle>();
+            TaskCompletionSource<Quadrangle> tcs = new TaskCompletionSource<Quadrangle>();
+
+            using (var cb = ObjectKeeper.Get(GetCallback(tcs)))
+            {
+                InteropImage.Track(source.Handle, trackingModel.Handle, EngineConfiguration.GetHandle(config),
+                    cb.Target).Validate("Failed to perform image tracking.");
+
+                return await tcs.Task;
+            }
+        }
 
-            // Define native callback
-            Interop.MediaVision.Image.MvImageTrackedCallback imageTrackedCb = (IntPtr sourceHandle, IntPtr imageTrackingModelHandle, IntPtr engineCfgHandle, IntPtr locationPtr, IntPtr userData) =>
+        private static InteropImage.TrackedCallback GetCallback(TaskCompletionSource<Quadrangle> tcs)
+        {
+            return (IntPtr sourceHandle, IntPtr imageTrackingModelHandle, IntPtr engineCfgHandle, IntPtr locationPtr, IntPtr _) =>
             {
                 try
                 {
-                    Quadrangle imageLocation = null;
+                    Quadrangle region = null;
                     if (locationPtr != IntPtr.Zero)
                     {
-                        Interop.MediaVision.Quadrangle location = (Interop.MediaVision.Quadrangle)Marshal.PtrToStructure(locationPtr, typeof(Interop.MediaVision.Quadrangle));
-                        imageLocation = new Quadrangle()
-                        {
-                            Points = new Point[4]
-                            {
-                            new Point(location.x1, location.y1),
-                            new Point(location.x2, location.y2),
-                            new Point(location.x3, location.y3),
-                            new Point(location.x4, location.y4)
-                            }
-                        };
-
-                        Log.Info(MediaVisionLog.Tag, String.Format("Image tracked, location : {0}", imageLocation.ToString()));
+                        region = Marshal.PtrToStructure<Interop.MediaVision.Quadrangle>(locationPtr).ToApiStruct();
                     }
 
-                    if (!tcsResult.TrySetResult(imageLocation))
+                    Log.Info(MediaVisionLog.Tag, $"Image tracked, region : {region}");
+
+                    if (!tcs.TrySetResult(region))
                     {
-                        Log.Info(MediaVisionLog.Tag, "Failed to set result");
-                        tcsResult.TrySetException(new InvalidOperationException("Failed to set result"));
+                        Log.Info(MediaVisionLog.Tag, "Failed to set track result");
                     }
                 }
-                catch (Exception ex)
+                catch (Exception e)
                 {
-                    Log.Info(MediaVisionLog.Tag, "exception :" + ex.ToString());
-                    tcsResult.TrySetException(ex);
+                    MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle track result", e);
+                    tcs.TrySetException(e);
                 }
             };
 
-            int ret = Interop.MediaVision.Image.Track(source._sourceHandle, trackingModel._trackingModelHandle, (config != null) ? config._engineHandle : IntPtr.Zero, imageTrackedCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to perform image tracking.");
-
-            return await tcsResult.Task;
         }
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/ImageTrackingConfiguration.cs b/src/Tizen.Multimedia/MediaVision/ImageTrackingConfiguration.cs
new file mode 100644 (file)
index 0000000..50b3b7f
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="ImageTracker"/>.
+    /// </summary>
+    public class ImageTrackingConfiguration : ImageRecognitionConfiguration
+    {
+        private const string KeyHistoryAmount = "MV_IMAGE_TRACKING_HISTORY_AMOUNT";
+        private const string KeyExpectedOffset = "MV_IMAGE_TRACKING_EXPECTED_OFFSET";
+        private const string KeyUseStabilization = "MV_IMAGE_TRACKING_USE_STABLIZATION";
+        private const string KeyStabilizationTolerantShift = "MV_IMAGE_TRACKING_STABLIZATION_TOLERANT_SHIFT";
+        private const string KeyStabilizationSpeed = "MV_IMAGE_TRACKING_STABLIZATION_SPEED";
+        private const string KeyStabilizationAccelaration = "MV_IMAGE_TRACKING_STABLIZATION_ACCELERATION";
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="HistoryAmount"/>.
+        /// </summary>
+        public static readonly int DefaultHistoryAmount = 3;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="ExpectedOffset"/>.
+        /// </summary>
+        public static readonly double DefaultExpectedOffset = 0;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="IsStabilizationEnabled"/>.
+        /// </summary>
+        public static readonly bool DefaultStabilizationEnabled = true;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="StabilizationTolerantShift"/>.
+        /// </summary>
+        public static readonly double DefaultStabilizationTolerantShift = 0.00006;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="StabilizationSpeed"/>.
+        /// </summary>
+        public static readonly double DefaultStabilizationSpeed = 0.3;
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="StabilizationAccelaration"/>.
+        /// </summary>
+        public static readonly double DefaultStabilizationAccelaration = 0.1;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ImageTrackingConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public ImageTrackingConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the number of recognition results in the tracking history.
+        /// </summary>
+        /// <value>
+        /// The number of previous recognition results, which will influence the stabilization.\n
+        /// The default is 3.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        public int HistoryAmount
+        {
+            get
+            {
+                return GetInt(KeyHistoryAmount);
+            }
+            set
+            {
+                if (value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(HistoryAmount), value,
+                        $"{nameof(HistoryAmount)} can't be less than zero.");
+                }
+                Set(KeyHistoryAmount, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the expected tracking offset.
+        /// </summary>
+        /// <value>
+        /// Relative offset value, for which the object offset is expected (relative to the object size in the current frame).\n
+        /// the default is 0.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception>
+        public double ExpectedOffset
+        {
+            get
+            {
+                return GetDouble(KeyExpectedOffset);
+            }
+            set
+            {
+                Set(KeyExpectedOffset, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the acceleration of the tracking stabilization.
+        /// </summary>
+        /// <value>
+        /// Acceleration will be used for image stabilization (relative to the distance from current location to stabilized location);
+        /// from 0 to 1, inclusive.\n
+        /// The default is 0.1.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="value"/> is less than zero.\n
+        ///     - or -\n
+        ///     <paramref name="value"/> is greater than one.
+        /// </exception>
+        public double StabilizationAccelaration
+        {
+            get
+            {
+                return GetDouble(KeyStabilizationAccelaration);
+            }
+            set
+            {
+                if (value < 0 || value > 1)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(value), value, "Valid range is 0 to 1 inclusive.");
+                }
+
+                Set(KeyStabilizationAccelaration, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the speed of the tracking stabilization.
+        /// </summary>
+        /// <value>
+        /// The start speed value used for image stabilization.\n
+        /// The default is 0.3.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception>
+        public double StabilizationSpeed
+        {
+            get
+            {
+                return GetDouble(KeyStabilizationSpeed);
+            }
+            set
+            {
+                Set(KeyStabilizationSpeed, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the relative tolerant shift for the tracking stabilization.
+        /// </summary>
+        /// <value>
+        /// It is component of tolerant shift which will be ignored by stabilization process.
+        /// (this value is relative to the object size in the current frame).
+        /// Tolerant shift will be computed like R * S + C, where R - value set to MV_IMAGE_TRACKING_STABLIZATION_TOLERANT_SHIFT,
+        /// S - area of object location on frame, C - constant value equal 1.3.\n
+        /// \n
+        /// The default is 0.00006.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception>
+        public double StabilizationTolerantShift
+        {
+            get
+            {
+                return GetDouble(KeyStabilizationTolerantShift);
+            }
+            set
+            {
+                Set(KeyStabilizationTolerantShift, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the state of the contour stabilization during tracking process.
+        /// </summary>
+        /// <value>
+        /// true if the contour stabilization is enabled; otherwise, false.\n
+        /// The default is true.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception>
+        public bool IsStabilizationEnabled
+        {
+            get
+            {
+                return GetBool(KeyUseStabilization);
+            }
+            set
+            {
+                Set(KeyUseStabilization, value);
+            }
+        }
+    }
+}
index 3cd6f53..f982ca9 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  */
 
 using System;
-using static Interop.MediaVision;
+using System.IO;
+using InteropModel = Interop.MediaVision.ImageTrackingModel;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents image tracking model interface
+    /// Represents the image tracking model interface.
     /// </summary>
-    public class ImageTrackingModel
+    public class ImageTrackingModel : IDisposable
     {
-        internal IntPtr _trackingModelHandle = IntPtr.Zero;
+        private IntPtr _handle = IntPtr.Zero;
         private bool _disposed = false;
 
         /// <summary>
-        /// Construct of ImageTrackingModel class
+        /// Initializes a new instance of the <see cref="ImageTrackingModel"/> class.
         /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
         public ImageTrackingModel()
         {
-            int ret = Interop.MediaVision.ImageTrackingModel.Create(out _trackingModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to create FaceTrackingModel.");
+            InteropModel.Create(out _handle).Validate("Failed to create FaceTrackingModel");
         }
 
         /// <summary>
-        /// Construct of ImageTrackingModel class which creates and loads tracking model from file.
+        /// Initializes a new instance of the <see cref="ImageTrackingModel"/> class with the specified path.
         /// </summary>
         /// <remarks>
-        /// ImageTrackingModel is loaded from the absolute path directory.\n
-        /// Models has been saved by <see cref="Save()"/> function can be loaded with this function
+        /// Model have been saved by <see cref="Save()"/> can be loaded.
         /// </remarks>
-        /// <param name="fileName">Name of path/file to load the model</param>
+        /// <param name="modelPath">Path to the model to load.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception>
+        /// <exception cref="System.IO.FileNotFoundException"><paramref name="modelPath"/> is invalid.</exception>
+        /// <exception cref="NotSupportedException">
+        ///     The feature is not supported.\n
+        ///     - or -\n
+        ///     <paramref name="modelPath"/> is not supported format.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception>
         /// <seealso cref="Save()"/>
-        /// <seealso cref="Prepare()"/>
-        /// <code>
-        /// 
-        /// </code>
-        public ImageTrackingModel(string fileName)
+        public ImageTrackingModel(string modelPath)
         {
-            int ret = Interop.MediaVision.ImageTrackingModel.Load(fileName, out _trackingModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to load ImageTrackingModel from file.");
+            if (modelPath == null)
+            {
+                throw new ArgumentNullException(nameof(modelPath));
+            }
+            InteropModel.Load(modelPath, out _handle).Validate("Failed to load ImageTrackingModel from file");
         }
 
-        /// <summary>
-        /// Destructor of the ImageTrackingModel class.
-        /// </summary>
         ~ImageTrackingModel()
         {
             Dispose(false);
@@ -67,47 +71,59 @@ namespace Tizen.Multimedia
         /// Sets target of image tracking model.\n
         /// Sets image object which will be tracked by using tracking functionality with this tracking model.
         /// </summary>
-        /// <param name="imageObject">Image object which will be set as target for tracking</param>
-        public void SetTarget(Image imageObject)
+        /// <param name="imageObject">Image object which will be set as the target for tracking.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="imageObject"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="ImageTrackingModel"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="imageObject"/> has already been disposed of.
+        /// </exception>
+        public void SetTarget(ImageObject imageObject)
         {
             if (imageObject == null)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new ArgumentNullException(nameof(imageObject));
             }
 
-            int ret = Interop.MediaVision.ImageTrackingModel.SetTarget(imageObject._imageObjectHandle, _trackingModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to set target of image tracking model");
+            InteropModel.SetTarget(imageObject.Handle, Handle).
+                Validate("Failed to set target of image tracking model");
         }
 
         /// <summary>
         /// Refreshes the state of image tracking model.\n
-        /// Clears moving history and change state to undetected. This function is usually called each time before tracking is started
+        /// Clears moving history and change state to undetected. It is usually called each time before tracking is started
         /// for the new sequence of sources which is not the direct continuation of the sequence for which tracking has been performed before.
         /// Tracking algorithm will try to find image by itself.
         /// </summary>
-        /// <param name="config">Image engine configuration. If null, default configuration will be used</param>
-        public void Refresh(ImageEngineConfiguration config = null)
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingModel"/> has already been disposed of.</exception>
+        public void Refresh()
         {
-            int ret = Interop.MediaVision.ImageTrackingModel.Refresh(_trackingModelHandle, (config != null) ? config._engineHandle : IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to refresh state");
+            InteropModel.Refresh(Handle, IntPtr.Zero).Validate("Failed to refresh state");
         }
 
         /// <summary>
-        /// Calls this method to save tracking model to the file.
+        /// Saves tracking model to the file.
         /// </summary>
-        /// <remarks>
-        /// TrackingModel is saved to the absolute path directory.
-        /// </remarks>
-        /// <param name="fileName">Name of the path/file to save the model</param>
-        public void Save(string fileName)
+        /// <param name="path">Path to the file to save the model.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingModel"/> has already been disposed of.</exception>
+        /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception>
+        public void Save(string path)
         {
-            if (string.IsNullOrEmpty(fileName))
+            if (path == null)
+            {
+                throw new ArgumentNullException(path);
+            }
+
+            var ret = InteropModel.Save(path, Handle);
+
+            if (ret == MediaVisionError.InvalidPath)
             {
-                throw new ArgumentException("Invalid file name");
+                throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist.");
             }
 
-            int ret = Interop.MediaVision.ImageTrackingModel.Save(fileName, _trackingModelHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to save tracking model to file");
+            ret.Validate("Failed to save tracking model to file");
         }
 
         public void Dispose()
@@ -123,13 +139,20 @@ namespace Tizen.Multimedia
                 return;
             }
 
-            if (disposing)
+            InteropModel.Destroy(_handle);
+            _disposed = true;
+        }
+
+        internal IntPtr Handle
+        {
+            get
             {
-                // Free managed objects
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(nameof(ImageTrackingModel));
+                }
+                return _handle;
             }
-
-            Interop.MediaVision.ImageTrackingModel.Destroy(_trackingModelHandle);
-            _disposed = true;
         }
     }
 }
old mode 100755 (executable)
new mode 100644 (file)
similarity index 66%
rename from src/Tizen.Multimedia/MediaVision/MediaVisionErrorFactory.cs
rename to src/Tizen.Multimedia/MediaVision/MediaVisionError.cs
index 6986b3d..4de8705
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -15,6 +15,7 @@
  */
 
 using System;
+using System.IO;
 using Tizen.Internals.Errors;
 
 namespace Tizen.Multimedia
@@ -84,51 +85,43 @@ namespace Tizen.Multimedia
         InvalidPath = MediaVisionErrorCode | 0x04
     }
 
-    internal static class MediaVisionErrorFactory
+    internal static class MediaVisionErrorExtensions
     {
-        internal static void CheckAndThrowException(int error, string msg)
+        public static void Validate(this MediaVisionError error, string msg)
         {
-            MediaVisionError e = (MediaVisionError)error;
-            if (e != MediaVisionError.None)
+            if (error == MediaVisionError.None)
             {
-                Log.Error(MediaVisionLog.Tag, String.Format("{0} : {1}", e.ToString(), msg));
-                throw GetException(error, msg);
+                return;
             }
-        }
 
-        internal static Exception GetException(int err, string msg)
-        {
-            MediaVisionError e = (MediaVisionError)err;
-            switch (e)
+            switch (error)
             {
-                case MediaVisionError.None:
-                    return null;
                 case MediaVisionError.NotSupported:
-                    throw new NotSupportedException("Not Supported: " + msg);
+                    throw new NotSupportedException(msg);
                 case MediaVisionError.MsgTooLong:
-                    throw new InvalidOperationException("Message too long: " + msg);
+                    throw new ArgumentException($"{msg} : Message too long.");
                 case MediaVisionError.NoData:
-                    throw new InvalidOperationException("No Data: " + msg);
+                    throw new InvalidOperationException($"{msg} : No Data.");
                 case MediaVisionError.KeyNotAvailable:
-                    throw new InvalidOperationException("Key Not Available: " + msg);
+                    throw new ArgumentException($"{msg} : Key Not Available.");
                 case MediaVisionError.OutOfMemory:
-                    throw new OutOfMemoryException("Out of Memory: " + msg);
+                    throw new OutOfMemoryException($"{msg} : Out of Memory.");
                 case MediaVisionError.InvalidParameter:
-                    throw new ArgumentException("Invalid Parameter: " + msg);
+                    throw new ArgumentException($"{msg} : Invalid argument.");
                 case MediaVisionError.InvalidOperation:
-                    throw new InvalidOperationException("Invalid Opertation: " + msg);
+                    throw new InvalidOperationException($"{msg} : Invalid Operation.");
                 case MediaVisionError.PermissionDenied:
-                    throw new UnauthorizedAccessException("Permission Denied: " + msg);
+                    throw new UnauthorizedAccessException($"{msg} : Permission Denied.");
                 case MediaVisionError.NotSupportedFormat:
-                    throw new InvalidOperationException("Not Supported Format: " + msg);
+                    throw new NotSupportedException($"{msg} : Not Supported Format.");
                 case MediaVisionError.Internal:
-                    throw new InvalidOperationException("Internal Error: " + msg);
+                    throw new InvalidOperationException($"{msg} : Internal Error.");
                 case MediaVisionError.InvalidData:
-                    throw new InvalidOperationException("Invalid Data: " + msg);
+                    throw new ArgumentException($"{msg} : Invalid Data.");
                 case MediaVisionError.InvalidPath:
-                    throw new InvalidOperationException("Invalid Path: " + msg);
+                    throw new FileNotFoundException($"{msg} : Invalid Path.");
                 default:
-                    throw new InvalidOperationException("Unknown Error: " + msg);
+                    throw new InvalidOperationException($"{msg} : Unknown Error.");
             }
         }
     }
index 44ca0e3..a4de14f 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  */
 
 using System;
-using System.Runtime.InteropServices;
-using static Interop.MediaVision;
+using System.Diagnostics;
+using InteropSource = Interop.MediaVision.MediaSource;
 
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents media vision source. An instance of this class has to be created \n
-    /// to keep information on image or video frame data as raw buffer. It can be created based on \n
-    /// the media data stored in memory or using the BaseMediaPacket class. \n
-    /// It provides a set of getters which allow to retrieve such image parameters as its size or colorspace (see Colorspace enumeration).
+    /// Represents the media vision source to keep information on image or video frame data as raw buffer.
     /// </summary>
-    public class MediaVisionSource : IDisposable
+    public class MediaVisionSource : IBufferOwner, IDisposable
     {
-        internal IntPtr _sourceHandle = IntPtr.Zero;
+        private IntPtr _handle = IntPtr.Zero;
         private bool _disposed = false;
 
+        internal MediaVisionSource()
+        {
+            InteropSource.Create(out _handle).Validate("Failed to create media vision source");
+        }
+
+        private MediaVisionSource(Action<IntPtr> fillAction)
+            : this()
+        {
+            try
+            {
+                fillAction(_handle);
+            }
+            catch(Exception)
+            {
+                InteropSource.Destroy(_handle);
+                throw;
+            }
+        }
+
+        private static void FillMediaPacket(IntPtr handle, MediaPacket mediaPacket)
+        {
+            Debug.Assert(handle != IntPtr.Zero);
+
+            if (mediaPacket == null)
+            {
+                throw new ArgumentNullException(nameof(mediaPacket));
+            }
+
+            InteropSource.FillMediaPacket(handle, mediaPacket.GetHandle()).
+                Validate("Failed to fill media packet");
+        }
+
         /// <summary>
-        /// The media vision source constructor
+        /// Initializes a new instance of the <see cref="MediaVisionSource"/> class based on the <see cref="MediaPacket"/>.
         /// </summary>
-        /// <code>
-        /// MediaVisionSource source = new MediaVisionSource();
-        /// </code>
-        public MediaVisionSource()
+        /// <param name="mediaPacket">The <see cref="MediaPacket"/> from which the source will be filled.</param>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="mediaPacket"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="mediaPacket"/> has already been disposed of.</exception>
+        public MediaVisionSource(MediaPacket mediaPacket)
+            : this(handle => FillMediaPacket(handle, mediaPacket))
+        {
+        }
+
+        private static void FillBuffer(IntPtr handle, byte[] buffer, uint width, uint height, Colorspace colorspace)
         {
-            int ret = Interop.MediaVision.MediaSource.Create(out _sourceHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to create media vision source.");
+            Debug.Assert(handle != IntPtr.Zero);
+
+            if (buffer == null)
+            {
+                throw new ArgumentNullException(nameof(buffer));
+            }
+
+            if (buffer.Length == 0)
+            {
+                throw new ArgumentException("Buffer.Length is zero.", nameof(buffer));
+            }
+
+            if (colorspace == Colorspace.Invalid)
+            {
+                throw new ArgumentException($"color space must not be {Colorspace.Invalid}.", nameof(colorspace));
+            }
+
+            ValidationUtil.ValidateEnum(typeof(Colorspace), colorspace, nameof(colorspace));
+
+            InteropSource.FillBuffer(handle, buffer, buffer.Length, width, height, colorspace).
+                Validate("Failed to fill buffer");
         }
 
         /// <summary>
-        /// Destructor of the MediaVisionSource class.
+        /// Initializes a new instance of the <see cref="MediaVisionSource"/> class based on the buffer and <see cref="Colorspace"/>.
         /// </summary>
+        /// <param name="buffer">The buffer of image data.</param>
+        /// <param name="width">The width of image.</param>
+        /// <param name="height">The height of image.</param>
+        /// <param name="colorspace">The image <see cref="Colorspace"/>.</param>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="buffer"/> has no element.(The length is zero.)\n
+        ///     - or -\n
+        ///     <paramref name="colorspace"/> is invalid.
+        /// </exception>
+        public MediaVisionSource(byte[] buffer, uint width, uint height, Colorspace colorspace)
+            : this(handle => FillBuffer(handle, buffer, width, height, colorspace))
+        {
+        }
+
         ~MediaVisionSource()
         {
             Dispose(false);
         }
 
+        private IMediaBuffer _buffer;
+
         /// <summary>
-        /// Gets buffer of the media source.
+        /// Gets the buffer of the media source.
         /// </summary>
-        /// <code>
-        /// 
-        /// </code>
-        public byte[] Buffer
+        /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception>
+        public IMediaBuffer Buffer
         {
             get
             {
-                IntPtr byteStrPtr;
-                int byteStrSize;
-                MediaVisionError ret = (MediaVisionError)Interop.MediaVision.MediaSource.GetBuffer(_sourceHandle, out byteStrPtr, out byteStrSize);
-                if (ret != MediaVisionError.None)
+                if (_buffer == null)
                 {
-                    Log.Error(MediaVisionLog.Tag, "[{0}] : Failed to get buffer data", ret.ToString());
-                    return null;
-                }
+                    IntPtr bufferHandle = IntPtr.Zero;
+                    int bufferSize = 0;
 
-                byte[] byteStr = new byte[byteStrSize];
-                if (byteStrSize > 0)
-                {
-                    Marshal.Copy(byteStrPtr, byteStr, 0, byteStrSize);
-                }
+                    InteropSource.GetBuffer(Handle, out bufferHandle, out bufferSize).
+                        Validate("Failed to get buffer");
 
-                return byteStr;
+                    _buffer = new DependentMediaBuffer(this, bufferHandle, bufferSize);
+                }
+                return _buffer;
             }
         }
 
         /// <summary>
         /// Gets height of the media source.
         /// </summary>
-        /// <code>
-        /// 
-        /// </code>
+        /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception>
         public uint Height
         {
             get
             {
                 uint height = 0;
-                MediaVisionError ret = (MediaVisionError)Interop.MediaVision.MediaSource.GetHeight(_sourceHandle, out height);
-                if (ret != MediaVisionError.None)
-                {
-                    Log.Error(MediaVisionLog.Tag, "[{0}] : Failed to get height", ret.ToString());
-                }
-
+                var ret = InteropSource.GetHeight(Handle, out height);
+                MultimediaDebug.AssertNoError(ret);
                 return height;
             }
         }
@@ -104,88 +163,33 @@ namespace Tizen.Multimedia
         /// <summary>
         /// Gets width of the media source.
         /// </summary>
-        /// <code>
-        /// 
-        /// </code>
+        /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception>
         public uint Width
         {
             get
             {
                 uint width = 0;
-                MediaVisionError ret = (MediaVisionError)Interop.MediaVision.MediaSource.GetWidth(_sourceHandle, out width);
-                if (ret != MediaVisionError.None)
-                {
-                    Log.Error(MediaVisionLog.Tag, "[{0}] : Failed to get width", ret.ToString());
-                }
-
+                var ret = InteropSource.GetWidth(Handle, out width);
+                MultimediaDebug.AssertNoError(ret);
                 return width;
             }
         }
 
         /// <summary>
-        /// Gets colorspace of the media source.
+        /// Gets <see cref="Colorspace"/> of the media source.
         /// </summary>
-        /// <code>
-        /// 
-        /// </code>
+        /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception>
         public Colorspace Colorspace
         {
             get
             {
                 Colorspace colorspace = Colorspace.Invalid;
-                MediaVisionError ret = (MediaVisionError)Interop.MediaVision.MediaSource.GetColorspace(_sourceHandle, out colorspace);
-                if (ret != MediaVisionError.None)
-                {
-                    Log.Error(MediaVisionLog.Tag, "[{0}] : Failed to get colorspace", ret.ToString());
-                }
-
+                var ret = InteropSource.GetColorspace(Handle, out colorspace);
+                MultimediaDebug.AssertNoError(ret);
                 return colorspace;
             }
         }
 
-        /// <summary>
-        /// Fills the media source based on the media packet.
-        /// </summary>
-        /// <param name="mediaPacket">The media packet from which the source will be filled</param>
-        /// <code>
-        /// 
-        /// </code>
-        /*public void FillMediaPacket(BaseMediaPacket mediaPacket)
-        {
-            int ret = Interop.MediaVision.MediaSource.FillBuffer(out _sourceHandle, mediaPacket._mediaPacketHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to fill media packet");
-        }*/
-
-        /// <summary>
-        /// Fills the media source based on the buffer and metadata.
-        /// </summary>
-        /// <param name="buffer">The buffer of image data</param>
-        /// <param name="width">The width of image data</param>
-        /// <param name="height">The height of image data</param>
-        /// <param name="colorspace">The image colorspace</param>
-        /// <seealso cref="Clear()"/>
-        /// <code>
-        /// 
-        /// </code>
-        public void FillBuffer(byte[] buffer, uint width, uint height, Colorspace colorspace)
-        {
-            int ret = Interop.MediaVision.MediaSource.FillBuffer(_sourceHandle, buffer, buffer.Length, width, height, colorspace);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to fill buffer");
-        }
-
-        /// <summary>
-        /// Clears the buffer of the media source.
-        /// </summary>
-        /// <seealso cref="FillBuffer()"/>
-        /// <code>
-        /// 
-        /// </code>
-        public void Clear()
-        {
-            int ret = Interop.MediaVision.MediaSource.Clear(_sourceHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to clear media source buffer");
-        }
-
         public void Dispose()
         {
             Dispose(true);
@@ -199,13 +203,30 @@ namespace Tizen.Multimedia
                 return;
             }
 
-            if (disposing)
+            InteropSource.Destroy(_handle);
+            _disposed = true;
+        }
+
+        internal IntPtr Handle
+        {
+            get
             {
-                // Free managed objects
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(nameof(MediaVisionSource));
+                }
+                return _handle;
             }
+        }
 
-            Interop.MediaVision.MediaSource.Destroy(_sourceHandle);
-            _disposed = true;
+        bool IBufferOwner.IsBufferAccessible(object buffer, MediaBufferAccessMode accessMode)
+        {
+            return true;
+        }
+
+        bool IBufferOwner.IsDisposed
+        {
+            get { return _disposed; }
         }
     }
 }
index d462555..4d2d747 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -20,22 +20,21 @@ using System.Collections.Generic;
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class is an event arguments of the MovementDetected event.
+    /// Provides data for the <see cref="MovementDetector.Detected"/> event.
     /// </summary>
     public class MovementDetectedEventArgs : EventArgs
     {
-        internal MovementDetectedEventArgs()
-        {
-        }
-
         /// <summary>
-        /// The identifier of the video source where event has been detected
+        /// Initializes a new instance of the <see cref="MovementDetectedEventArgs"/> class.
         /// </summary>
-        public int VideoStreamId { get; internal set; }
+        public MovementDetectedEventArgs(IEnumerable<Rectangle> areas)
+        {
+            Areas = areas;
+        }
 
         /// <summary>
         /// Gets a set of rectangular regions where movement was detected.
         /// </summary>
-        public List<Rectangle> Regions { get; internal set; }
+        public IEnumerable<Rectangle> Areas { get; }
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/MovementDetectionConfiguration.cs b/src/Tizen.Multimedia/MediaVision/MovementDetectionConfiguration.cs
new file mode 100644 (file)
index 0000000..bb7db95
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents concrete EngineConfig for creation of video surveillance systems.
+    /// </summary>
+    public class MovementDetectionConfiguration : SurveillanceEngineConfiguration
+    {
+        private const string KeyThreshold = "MV_SURVEILLANCE_MOVEMENT_DETECTION_THRESHOLD";
+
+        /// <summary>
+        /// Represents a configuration of <see cref="MovementDetector"/>.
+        /// </summary>
+        public static readonly int DefaultThreshold = 10;
+
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MovementDetectionConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public MovementDetectionConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets movement detection threshold.\n
+        /// This value might be set before subscription on <see cref="MovementDetector.Detected"/> event
+        /// to specify the sensitivity of the movement detector.
+        /// </summary>
+        /// <value>
+        /// The value indicating the sensitivity of the <see cref="MovementDetector"/> from 0 to 255 inclusive
+        /// where 255 means that no movements will be detected and 0 means that all frame changes
+        /// will be interpreted as movements.\n
+        /// The default is 10.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="MovementDetectionConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="value"/> is less than zero.\n
+        ///     - or -\n
+        ///     <paramref name="value"/> is greater than 255.
+        /// </exception>
+        public int Threshold
+        {
+            get
+            {
+                return GetInt(KeyThreshold);
+            }
+            set
+            {
+                if (value < 0 || value > 255)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(Threshold), value,
+                        $"Valid {nameof(Threshold)} range is 0 to 255 inclusive");
+                }
+
+                Set(KeyThreshold, value);
+            }
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/MovementDetectionEventTrigger.cs b/src/Tizen.Multimedia/MediaVision/MovementDetectionEventTrigger.cs
deleted file mode 100755 (executable)
index 4eecca5..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class representsmovement detection event trigger.
-    /// </summary>
-    public class MovementDetectionEventTrigger : SurveillanceEventTrigger
-    {
-        /// <summary>
-        /// Constructor of MovementDetectionEventTrigger class
-        /// </summary>
-        public MovementDetectionEventTrigger() : base(SurveillanceEventTrigger.MovementDetectedType)
-        {
-        }
-
-        /// <summary>
-        /// This is event for a movement detection. The result will be position of regions where movement has been detected.
-        /// </summary>
-        public event EventHandler<MovementDetectedEventArgs> MovementDetected
-        {
-            add
-            {
-                base.MovementDetectedEvent += value;
-            }
-
-            remove
-            {
-                base.MovementDetectedEvent -= value;
-            }
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/MovementDetector.cs b/src/Tizen.Multimedia/MediaVision/MovementDetector.cs
new file mode 100644 (file)
index 0000000..a989a7c
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using static Interop.MediaVision.Surveillance;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides the ability to detect movement on image sources.
+    /// </summary>
+    /// <seealso cref="MovementDetectionConfiguration"/>
+    public class MovementDetector : SurveillanceEngine
+    {
+        private const string KeyNumberOfRegions = "NUMBER_OF_MOVEMENT_REGIONS";
+        private const string KeyRegions = "MOVEMENT_REGIONS";
+
+        private const string MovementDetectedEventType = "MV_SURVEILLANCE_EVENT_MOVEMENT_DETECTED";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MovementDetector"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public MovementDetector() : base(MovementDetectedEventType)
+        {
+        }
+
+        /// <summary>
+        /// Occurs when the movement detected.
+        /// </summary>
+        /// <remarks>The event handler will be executed on an internal thread.</remarks>
+        public event EventHandler<MovementDetectedEventArgs> Detected;
+
+        internal override void OnEventDetected(IntPtr trigger, IntPtr source, int streamId,
+            IntPtr result, IntPtr _)
+        {
+            try
+            {
+                Detected?.Invoke(this, CreateMovementDetectedEventArgs(result));
+            }
+            catch (Exception e)
+            {
+                MultimediaLog.Error(MediaVisionLog.Tag, "Failed to invoke Recognized event.", e);
+            }
+        }
+
+        private static Rectangle[] RetrieveAreas(IntPtr result)
+        {
+            int count = 0;
+            GetResultValue(result, KeyNumberOfRegions, out count).Validate("Failed to get result count");
+
+            if (count == 0)
+            {
+                return new Rectangle[0];
+            }
+
+            var rects = new Interop.MediaVision.Rectangle[count];
+
+            GetResultValue(result, KeyRegions, rects).Validate("Failed to get regions");
+
+            return Interop.ToApiStruct(rects);
+        }
+
+        private static MovementDetectedEventArgs CreateMovementDetectedEventArgs(IntPtr result)
+        {
+            return new MovementDetectedEventArgs(RetrieveAreas(result));
+        }
+
+
+        /// <summary>
+        /// Adds <see cref="SurveillanceSource"/>.
+        /// </summary>
+        /// <param name="source">The source used for recognition.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="MovementDetector"/> has already been disposed of.</exception>
+        /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/>
+        public void AddSource(SurveillanceSource source)
+        {
+            AddSource(source, null);
+        }
+
+        /// <summary>
+        /// Adds <see cref="SurveillanceSource"/> with the provided <see cref="MovementDetectionConfiguration"/>.
+        /// </summary>
+        /// <param name="source">The source used for recognition.</param>
+        /// <param name="config">The config for the <paramref name="source"/>. This value can be null.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="MovementDetector"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/>
+        public void AddSource(SurveillanceSource source, MovementDetectionConfiguration config)
+        {
+            InvokeAddSource(source, config);
+        }
+
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/PersonAppearanceChangedEventArgs.cs b/src/Tizen.Multimedia/MediaVision/PersonAppearanceChangedEventArgs.cs
deleted file mode 100755 (executable)
index 72696a6..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-using System.Collections.Generic;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class is an event arguments of the PersonAppearanceChanged event.
-    /// </summary>
-    public class PersonAppearanceChangedEventArgs : EventArgs
-    {
-        internal PersonAppearanceChangedEventArgs()
-        {
-        }
-
-        /// <summary>
-        /// The identifier of the video source where event has been detected
-        /// </summary>
-        public int VideoStreamId { get; internal set; }
-
-        /// <summary>
-        /// Gets a set of rectangular locations where appearances of the persons were detected.
-        /// </summary>
-        public List<Rectangle> AppearedLocations { get; internal set; }
-
-        /// <summary>
-        /// Gets a set of rectangular locations where disappearances of the persons were detected.
-        /// </summary>
-        public List<Rectangle> DisappearedLocations { get; internal set; }
-
-        /// <summary>
-        /// Gets a set of rectangular locations where persons were tracked.
-        /// </summary>
-        public List<Rectangle> TrackedLocations { get; internal set; }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/PersonAppearanceDetectedEventArgs.cs b/src/Tizen.Multimedia/MediaVision/PersonAppearanceDetectedEventArgs.cs
new file mode 100644 (file)
index 0000000..1762241
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides data for the <see cref="PersonAppearanceDetector.Detected"/> event.
+    /// </summary>
+    public class PersonAppearanceDetectedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PersonAppearanceDetectedEventArgs"/> class.
+        /// </summary>
+        public PersonAppearanceDetectedEventArgs(IEnumerable<Rectangle> appeared,
+            IEnumerable<Rectangle> disappeared, IEnumerable<Rectangle> tracked)
+        {
+            AppearanceAreas = appeared;
+            DisappearanceAreas = disappeared;
+            TrackedAreas = tracked;
+        }
+
+        /// <summary>
+        /// Gets a set of rectangular regions where appearances of the persons were detected.
+        /// </summary>
+        public IEnumerable<Rectangle> AppearanceAreas { get; }
+
+        /// <summary>
+        /// Gets a set of rectangular regions where disappearances of the persons were detected.
+        /// </summary>
+        public IEnumerable<Rectangle> DisappearanceAreas { get; }
+
+        /// <summary>
+        /// Gets a set of rectangular regions where persons were tracked.
+        /// </summary>
+        public IEnumerable<Rectangle> TrackedAreas { get; }
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/PersonAppearanceDetectionConfiguration.cs b/src/Tizen.Multimedia/MediaVision/PersonAppearanceDetectionConfiguration.cs
new file mode 100644 (file)
index 0000000..bf8aafa
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="PersonAppearanceDetector"/> instances.
+    /// </summary>
+    public class PersonAppearanceDetectionConfiguration : SurveillanceEngineConfiguration
+    {
+        private const string KeySkipFramesCount = "MV_SURVEILLANCE_SKIP_FRAMES_COUNT";
+
+        /// <summary>
+        /// A read-only field that represents the default value of <see cref="SkipFramesCount"/>.
+        /// </summary>
+        public static readonly int DefaultSkipFramesCount = 0;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PersonAppearanceDetectionConfiguration"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public PersonAppearanceDetectionConfiguration()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets how many frames will be skipped during push source.\n
+        /// </summary>
+        /// <value>
+        /// The value to specify the number of <see cref="MediaVisionSource"/> calls will be ignored by subscription
+        /// of the event trigger.\n
+        ///
+        /// The default is 0. It means that no frames will be skipped and all <see cref="MediaVisionSource"/> will
+        /// be processed.
+        /// </value>
+        /// <exception cref="ObjectDisposedException">The <see cref="PersonAppearanceDetectionConfiguration"/> already has been disposed of.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+        /// <seealso cref="SurveillanceSource.Push(MediaVisionSource)"/>
+        public int SkipFramesCount
+        {
+            get
+            {
+                return GetInt(KeySkipFramesCount);
+            }
+            set
+            {
+                if (value < 0)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(SkipFramesCount), value,
+                        $"{nameof(SkipFramesCount)} can't be less than zero.");
+                }
+                Set(KeySkipFramesCount, value);
+            }
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/PersonAppearanceDetector.cs b/src/Tizen.Multimedia/MediaVision/PersonAppearanceDetector.cs
new file mode 100644 (file)
index 0000000..029d38f
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using static Interop.MediaVision.Surveillance;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides the ability to detect person appearance changes on image sources.
+    /// </summary>
+    /// <seealso cref="PersonAppearanceDetectionConfiguration"/>
+    public class PersonAppearanceDetector : SurveillanceEngine
+    {
+        private const string KeyAppearedNumber = "NUMBER_OF_APPEARED_PERSONS";
+        private const string KeyDisappearedNumber = "NUMBER_OF_DISAPPEARED_PERSONS";
+        private const string KeyTrackedNumber = "NUMBER_OF_TRACKED_PERSONS";
+        private const string KeyAppearedLocations = "APPEARED_PERSONS_LOCATIONS";
+        private const string KeyDisappearedLocations = "DISAPPEARED_PERSONS_LOCATIONS";
+        private const string KeyTrackedLocations = "TRACKED_PERSONS_LOCATIONS";
+
+        private const string PersonAppearanceEventType = "MV_SURVEILLANCE_EVENT_PERSON_APPEARED_DISAPEARED";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PersonAppearanceDetector"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public PersonAppearanceDetector() : base(PersonAppearanceEventType)
+        {
+        }
+
+        /// <summary>
+        /// Occurs when the any appearance changes detected.
+        /// </summary>
+        /// <remarks>The event handler will be executed on an internal thread.</remarks>
+        public event EventHandler<PersonAppearanceDetectedEventArgs> Detected;
+
+        internal override void OnEventDetected(IntPtr trigger, IntPtr source, int streamId,
+            IntPtr result, IntPtr _)
+        {
+            try
+            {
+                Detected?.Invoke(this, CreatePersonAppearanceChangedEventArgs(result));
+            }
+            catch (Exception e)
+            {
+                MultimediaLog.Error(MediaVisionLog.Tag, "Failed to invoke Recognized event.", e);
+            }
+        }
+
+
+        private PersonAppearanceDetectedEventArgs CreatePersonAppearanceChangedEventArgs(IntPtr result)
+        {
+            return new PersonAppearanceDetectedEventArgs(
+                GetResultAreas(result, KeyAppearedNumber, KeyAppearedLocations),
+                GetResultAreas(result, KeyDisappearedNumber, KeyDisappearedLocations),
+                GetResultAreas(result, KeyTrackedNumber, KeyTrackedLocations)
+                );
+        }
+
+        private static Rectangle[] GetResultAreas(IntPtr result, string countKey, string regionsKey)
+        {
+            int count = 0;
+            GetResultValue(result, countKey, out count).Validate("Failed to get result");
+
+            var rects = new Interop.MediaVision.Rectangle[count];
+            if (count > 0)
+            {
+                GetResultValue(result, regionsKey, rects).Validate("Failed to get result");
+            }
+
+            return Interop.ToApiStruct(rects);
+        }
+
+        /// <summary>
+        /// Adds <see cref="SurveillanceSource"/>.
+        /// </summary>
+        /// <param name="source">The source used for recognition.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="PersonAppearanceDetector"/> has already been disposed of.</exception>
+        /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/>
+        public void AddSource(SurveillanceSource source)
+        {
+            AddSource(source, null);
+        }
+
+        /// <summary>
+        /// Adds <see cref="SurveillanceSource"/> with the provided <see cref="PersonAppearanceDetectionConfiguration"/>.
+        /// </summary>
+        /// <param name="source">The source used for recognition.</param>
+        /// <param name="config">The config for the <paramref name="source"/>. This value can be null.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="PersonAppearanceDetector"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/>
+        public void AddSource(SurveillanceSource source, PersonAppearanceDetectionConfiguration config)
+        {
+            InvokeAddSource(source, config);
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/PersonAppearanceEventTrigger.cs b/src/Tizen.Multimedia/MediaVision/PersonAppearanceEventTrigger.cs
deleted file mode 100755 (executable)
index d31dfe5..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents person appearance event trigger.
-    /// </summary>
-    public class PersonAppearanceEventTrigger : SurveillanceEventTrigger
-    {
-        /// <summary>
-        /// Constructor of PersonAppearanceEventTrigger class
-        /// </summary>
-        public PersonAppearanceEventTrigger() : base(SurveillanceEventTrigger.PersonAppearanceChangedType)
-        {
-        }
-
-        /// <summary>
-        /// This is event for a person appearing (disappearing). The result will be:
-        /// * positions of person, which were appeared;
-        /// * positions of persons, which were tracked;
-        /// * positions of persons, which were disappeared.
-        /// </summary>
-        public event EventHandler<PersonAppearanceChangedEventArgs> PersonAppearanceChanged
-        {
-            add
-            {
-                base.PersonAppearanceChangedEvent += value;
-            }
-
-            remove
-            {
-                base.PersonAppearanceChangedEvent -= value;
-            }
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/PersonRecognitionConfiguration.cs b/src/Tizen.Multimedia/MediaVision/PersonRecognitionConfiguration.cs
new file mode 100644 (file)
index 0000000..9a8ca01
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Represents a configuration of <see cref="PersonRecognizer"/> instances.
+    /// </summary>
+    public class PersonRecognitionConfiguration : SurveillanceEngineConfiguration
+    {
+        private const string KeyFaceRecognitionModelFilePath = "MV_SURVEILLANCE_FACE_RECOGNITION_MODEL_FILE_PATH";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PersonRecognitionConfiguration"/> class.
+        /// </summary>
+        /// <param name="modelPath">Path to the face recognition model.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public PersonRecognitionConfiguration(string modelPath)
+        {
+            FaceRecognitionModelPath = modelPath;
+        }
+
+        /// <summary>
+        /// Gets or sets face recognition model file path.
+        /// </summary>
+        /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="PersonRecognitionConfiguration"/> already has been disposed of.</exception>
+        public string FaceRecognitionModelPath
+        {
+            get
+            {
+                return GetString(KeyFaceRecognitionModelFilePath);
+            }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException(nameof(FaceRecognitionModelPath));
+                }
+                Set(KeyFaceRecognitionModelFilePath, value);
+            }
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/PersonRecognitionEventTrigger.cs b/src/Tizen.Multimedia/MediaVision/PersonRecognitionEventTrigger.cs
deleted file mode 100755 (executable)
index 3b6da67..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents person recognition event trigger.
-    /// </summary>
-    public class PersonRecognitionEventTrigger : SurveillanceEventTrigger
-    {
-        /// <summary>
-        /// Constructor of PersonRecognizedEventTrigger class
-        /// </summary>
-        public PersonRecognitionEventTrigger() : base(SurveillanceEventTrigger.PersonRecognizedType)
-        {
-        }
-
-        /// <summary>
-        /// This is an event for a person recognition. The result will be positions (face locations) of persons, which were recognized,
-        /// their labels and confidences of the recognition models
-        /// </summary>
-        public event EventHandler<PersonRecognizedEventArgs> PersonRecognized
-        {
-            add
-            {
-                base.PersonRecognizedEvent += value;
-            }
-
-            remove
-            {
-                base.PersonRecognizedEvent -= value;
-            }
-        }
-    }
-}
old mode 100755 (executable)
new mode 100644 (file)
similarity index 53%
rename from src/Tizen.Multimedia/MediaVision/PersonRecognitionResult.cs
rename to src/Tizen.Multimedia/MediaVision/PersonRecognitionInfo.cs
index d95b8f1..f80d345
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents result of person recognition event trigger.
+    /// Represents a result of <see cref="PersonRecognizer"/> instances.
     /// </summary>
-    public class PersonRecognitionResult
+    public class PersonRecognitionInfo
     {
-        internal PersonRecognitionResult()
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PersonRecognitionInfo"/> class.
+        /// </summary>
+        public PersonRecognitionInfo(Rectangle area, int label, double confidence)
         {
+            Area = area;
+            Label = label;
+            Confidence = confidence;
         }
 
         /// <summary>
-        /// Gets a rectangular locations where person face was recognized.
+        /// Gets the rectangular location where person face was recognized.
         /// </summary>
-        public Rectangle Location { get; internal set; }
+        public Rectangle Area { get; }
 
         /// <summary>
-        /// Gets a label that correspond to the recognized person.
+        /// Gets the label that correspond to the recognized person.
         /// </summary>
-        public int Label { get; internal set; }
+        public int Label { get; }
 
         /// <summary>
-        /// Gets a confidence value that correspond to the recognized person.
+        /// Gets the confidence value that correspond to the recognized person.
         /// </summary>
-        public double Confidence { get; internal set; }
+        public double Confidence { get; }
     }
 }
index 64f65cb..d524618 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -20,22 +20,21 @@ using System.Collections.Generic;
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class is an event arguments of the PersonRecognized event.
+    /// Provides data for the <see cref="PersonRecognizer.Recognized"/> event.
     /// </summary>
     public class PersonRecognizedEventArgs : EventArgs
     {
-        internal PersonRecognizedEventArgs()
-        {
-        }
-
         /// <summary>
-        /// The identifier of the video source where event has been detected
+        /// Initializes a new instance of the <see cref="PersonRecognizedEventArgs"/> class.
         /// </summary>
-        public int VideoStreamId { get; internal set; }
+        public PersonRecognizedEventArgs(IEnumerable<PersonRecognitionInfo> recognitionInfo)
+        {
+            Recongnitions = recognitionInfo;
+        }
 
         /// <summary>
-        /// Gets a set of information that correspond to the recognized persons
+        /// Gets a set of information that correspond to the recognized persons.
         /// </summary>
-        public List<PersonRecognitionResult> Result { get; internal set; }
+        public IEnumerable<PersonRecognitionInfo> Recongnitions { get; }
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/PersonRecognizer.cs b/src/Tizen.Multimedia/MediaVision/PersonRecognizer.cs
new file mode 100644 (file)
index 0000000..63f12ff
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using static Interop.MediaVision.Surveillance;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides the ability to recognize person on image sources.
+    /// </summary>
+    /// <seealso cref="PersonRecognitionConfiguration"/>
+    public class PersonRecognizer : SurveillanceEngine
+    {
+        private const string KeyCount = "NUMBER_OF_PERSONS";
+        private const string KeyLocations = "PERSONS_LOCATIONS";
+        private const string KeyLabels = "PERSONS_LABELS";
+        private const string KeyConfidences = "PERSONS_CONFIDENCES";
+
+        private const string PersonRecognizedEventType = "MV_SURVEILLANCE_EVENT_PERSON_RECOGNIZED";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PersonRecognizer"/> class.
+        /// </summary>
+        /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+        public PersonRecognizer() : base(PersonRecognizedEventType)
+        {
+        }
+
+        /// <summary>
+        /// Occurs when a person recognized.
+        /// </summary>
+        /// <remarks>The event handler will be executed on an internal thread.</remarks>
+        /// <seealso cref="PersonRecognitionConfiguration.FaceRecognitionModelPath"/>
+        public event EventHandler<PersonRecognizedEventArgs> Recognized;
+
+        internal override void OnEventDetected(IntPtr trigger, IntPtr source, int streamId,
+            IntPtr result, IntPtr _)
+        {
+            try
+            {
+                Recognized?.Invoke(this, CreatePersonRecognizedEventArgs(result));
+            }
+            catch (Exception e)
+            {
+                MultimediaLog.Error(MediaVisionLog.Tag, "Failed to invoke Recognized event.", e);
+            }
+        }
+
+        private PersonRecognizedEventArgs CreatePersonRecognizedEventArgs(IntPtr result)
+        {
+            int count;
+
+            GetResultValue(result, KeyCount, out count).Validate("Failed to get result count");
+
+            var recognitionInfo = new PersonRecognitionInfo[count];
+
+            if (count > 0)
+            {
+                var rects = new Interop.MediaVision.Rectangle[count];
+                GetResultValue(result, KeyLocations, rects).Validate("Failed to get location");
+
+                var labels = new int[count];
+                GetResultValue(result, KeyLabels, labels).Validate("Failed to get label");
+
+                var confidences = new double[count];
+                GetResultValue(result, KeyConfidences, confidences).Validate("Failed to get confidence");
+
+                for (int i = 0; i < count; i++)
+                {
+                    recognitionInfo[i] = new PersonRecognitionInfo(rects[i].ToApiStruct(),
+                        labels[i], confidences[i]);
+                }
+            }
+
+            return new PersonRecognizedEventArgs(recognitionInfo);
+        }
+
+        /// <summary>
+        /// Adds <see cref="SurveillanceSource"/> with the provided <see cref="PersonRecognitionConfiguration"/>.
+        /// </summary>
+        /// <param name="source">The source used for recognition.</param>
+        /// <param name="config">The config for the <paramref name="source"/>.</param>
+        /// <exception cref="ArgumentNullException">
+        ///     <paramref name="source"/> is null.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> is null.
+        /// </exception>
+        /// <exception cref="ObjectDisposedException">
+        ///     The <see cref="PersonRecognizer"/> has already been disposed of.\n
+        ///     - or -\n
+        ///     <paramref name="config"/> has already been disposed of.
+        /// </exception>
+        /// <exception cref="System.IO.FileNotFoundException">
+        /// <see cref="PersonRecognitionConfiguration.FaceRecognitionModelPath"/> of <paramref name="config"/> does not exists.
+        /// </exception>
+        /// <exception cref="UnauthorizedAccessException">
+        /// No permission to access to the <see cref="PersonRecognitionConfiguration.FaceRecognitionModelPath"/>.
+        /// </exception>
+        /// <exception cref="NotSupportedException">The model file is not supported format or file.</exception>
+        /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/>
+        public void AddSource(SurveillanceSource source, PersonRecognitionConfiguration config)
+        {
+            if (config == null)
+            {
+                throw new ArgumentNullException(nameof(config));
+            }
+            InvokeAddSource(source, config);
+        }
+    }
+}
index 8da6afd..817dedb 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  * limitations under the License.
  */
 
+using System;
+
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents the configuration details for the QR code to be generated by BarcodeGenerator
+    /// Represents a QR configuration of <see cref="BarcodeGenerator"/>.
     /// </summary>
     public class QrConfiguration
     {
         /// <summary>
-        /// The constructor of the QrConfig class
+        /// Initializes a new instance of the <see cref="QrConfiguration"/> class.
         /// </summary>
-        /// <param name="qrMode">Encoding mode for the message (only for QR codes; for 1D barcodes set this parameter to Unavailable)</param>
-        /// <param name="ecc">Error correction level (only for QR codes; for 1D barcodes set this parameter to Unavailable)</param>
-        /// <param name="version">QR code version (for 1D barcodes set this parameter to 0)</param>
+        /// <param name="qrMode">Encoding mode for the message.</param>
+        /// <param name="ecc">Error correction level.</param>
+        /// <param name="version">QR code version. From 1 to 40 inclusive.</param>
         /// <code>
         /// var obj = new QrConfiguration(QrMode.Numeric, ErrorCorrectionLevel.Medium, 30);
         /// </code>
+        /// <exception cref="ArgumentOutOfRangeException">
+        ///     <paramref name="version"/> is less than 1.\n
+        ///     - or -\n
+        ///     <paramref name="version"/> is greater than 40.
+        /// </exception>
+        /// <exception cref="ArgumentException">
+        ///     <paramref name="qrMode"/> is invalid.\n
+        ///     - or -
+        ///     <paramref name="ecc"/> is invalid.
+        /// </exception>
         public QrConfiguration(QrMode qrMode, ErrorCorrectionLevel ecc, int version)
         {
+            if (version < 1 || version > 40)
+            {
+                throw new ArgumentOutOfRangeException(nameof(version), version,
+                    "Valid version range is 1 to 40 inclusive.");
+            }
+            ValidationUtil.ValidateEnum(typeof(QrMode), qrMode, nameof(qrMode));
+            ValidationUtil.ValidateEnum(typeof(ErrorCorrectionLevel), ecc, nameof(ecc));
+
             Mode = qrMode;
             ErrorCorrectionLevel = ecc;
             Version = version;
         }
 
         /// <summary>
-        /// Gets encoding mode for the message (only for QR codes; for 1D barcodes set this value to Unavailable)
+        /// Gets the encoding mode for the message.
         /// </summary>
         public QrMode Mode { get; }
 
         /// <summary>
-        /// Gets error correction level (only for QR codes; for 1D barcodes set this value to Unavailable)
+        /// Gets the error correction level.
         /// </summary>
         public ErrorCorrectionLevel ErrorCorrectionLevel { get; }
 
         /// <summary>
-        /// Gets QR code version (for 1D barcodes set this value to 0)
+        /// Gets the QR code version.
         /// </summary>
         public int Version { get; }
     }
index ca644d4..ac4d0f5 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// Enumeration for supported QR code encoding mode.
+    /// Specifies the supported QR code encoding mode.
     /// </summary>
     public enum QrMode
     {
         /// <summary>
-        /// Numeric digits
+        /// Numeric digits.
         /// </summary>
         Numeric,
         /// <summary>
-        /// Alphanumeric characters
+        /// Alphanumeric characters, '$', '%', '*', '+', '-', '.', '/' and ':'.
         /// </summary>
         AlphaNumeric,
         /// <summary>
-        /// Raw 8-bit bytes
+        /// Raw 8-bit bytes.
         /// </summary>
         Byte,
         /// <summary>
-        /// UTF-8 character encoding
+        /// UTF-8 character encoding.
         /// </summary>
-        Utf8,
-        /// <summary>
-        /// Unavailable
-        /// </summary>
-        Unavailable
+        Utf8
     }
 }
index 246e4f4..ec0e562 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
@@ -19,38 +19,32 @@ using System;
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents location of the object bounded by quadrangle defined by four 2D points.
+    /// Represents a region with 4 <see cref="Point"/>s.
     /// </summary>
     public class Quadrangle
     {
-        internal Quadrangle()
-        {
-
-        }
-
         /// <summary>
         /// The constructor of the Quadrangle class
         /// </summary>
-        /// <param name="points">four points that define object bounding quadrangle</param>
+        /// <remarks><paramref name="points"/> must have 4 elements</remarks>
+        /// <param name="points">four points that define object bounding quadrangle.</param>
+        /// <exception cref="ArgumentException">The Length of <paramref name="points"/> is not 4.</exception>
         public Quadrangle(Point[] points)
         {
             if (points.Length != 4)
             {
-                throw new ArgumentException("Invalid parameter");
+                throw new ArgumentException($"{points} must have 4 elements.");
             }
 
             Points = points;
         }
 
         /// <summary>
-        /// Gets four points that define object bounding quadrangle
+        /// Gets four points that define the object bounding quadrangle.
         /// </summary>
-        public Point[] Points { get; internal set; }
+        public Point[] Points { get; }
 
-        internal new string ToString()
-        {
-            return string.Format("[{0}, {1}, {2}, {3}]", Points[0].ToString(), Points[1].ToString(),
-                Points[2].ToString(), Points[3].ToString());
-        }
+        public override string ToString() =>
+            $"[{{{Points[0].ToString()}}}, {{{Points[1].ToString()}}}, {{{Points[2].ToString()}}}, {{{Points[3].ToString()}}}]";
     }
 }
old mode 100755 (executable)
new mode 100644 (file)
similarity index 66%
rename from src/Tizen.Multimedia/MediaVision/FaceDetectionResult.cs
rename to src/Tizen.Multimedia/MediaVision/SurveillanceConfiguration.cs
index 9443982..3024ae2
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the License);
  * limitations under the License.
  */
 
-using System.Collections.Generic;
-
 namespace Tizen.Multimedia
 {
     /// <summary>
-    /// This class represents result of face detection operation.
+    /// SurveillanceEngineConfiguration is a base class for surveillance configurations.
     /// </summary>
-    public class FaceDetectionResult
+    public class SurveillanceEngineConfiguration : EngineConfiguration
     {
-        internal FaceDetectionResult()
+        internal SurveillanceEngineConfiguration()
         {
         }
-
-        /// <summary>
-        /// Gets the rectangular locations of the detected faces.
-        /// </summary>
-        public List<Rectangle> Locations { get; internal set; }
     }
 }
diff --git a/src/Tizen.Multimedia/MediaVision/SurveillanceEngine.cs b/src/Tizen.Multimedia/MediaVision/SurveillanceEngine.cs
new file mode 100644 (file)
index 0000000..bf0c87c
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using static Interop.MediaVision.Surveillance;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// SurveillanceEngine is a base class for surveillance event triggers.
+    /// Media Vision Surveillance provides functionality can be utilized for creation of video surveillance systems.
+    /// </summary>
+    /// <seealso cref="MovementDetector"/>
+    /// <seealso cref="PersonAppearanceDetector"/>
+    /// <seealso cref="PersonRecognizer"/>
+    public abstract class SurveillanceEngine : IDisposable
+    {
+        private IntPtr _handle = IntPtr.Zero;
+        private bool _disposed = false;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SurveillanceEngine"/> class.
+        /// </summary>
+        /// <param name="eventType">The type of the event trigger</param>
+        internal SurveillanceEngine(string eventType)
+        {
+            EventTriggerCreate(eventType, out _handle).Validate("Failed to create surveillance event trigger.");
+        }
+
+        ~SurveillanceEngine()
+        {
+            Dispose(false);
+        }
+
+        internal IntPtr Handle
+        {
+            get
+            {
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException(GetType().Name);
+                }
+                return _handle;
+            }
+        }
+
+        /// <summary>
+        /// Sets and gets ROI (Region Of Interest) to the event trigger
+        /// </summary>
+        /// <exception cref="ObjectDisposedException">The <see cref="SurveillanceEngine"/> has already been disposed of.</exception>
+        public Point[] Roi
+        {
+            get
+            {
+                IntPtr roiPtr = IntPtr.Zero;
+                try
+                {
+                    int count = 0;
+                    GetEventTriggerRoi(Handle, out count, out roiPtr).Validate("Failed to get roi");
+
+                    Point[] points = new Point[count];
+                    IntPtr iterPtr = roiPtr;
+
+                    for (int i = 0; i < count; i++)
+                    {
+                        points[i] = Marshal.PtrToStructure<Interop.MediaVision.Point>(roiPtr).ToApiStruct();
+                        iterPtr = IntPtr.Add(iterPtr, Marshal.SizeOf<Interop.MediaVision.Point>());
+                    }
+
+                    return points;
+                }
+                finally
+                {
+                    Interop.Libc.Free(roiPtr);
+                }
+            }
+            set
+            {
+                int length = value == null ? 0 : value.Length;
+
+                var points = value == null ? null : Interop.ToMarshalable(value);
+
+                SetEventTriggerRoi(Handle, length, points).Validate("Failed to set roi");
+            }
+        }
+
+        internal abstract void OnEventDetected(IntPtr trigger, IntPtr source,
+            int streamId, IntPtr eventResult, IntPtr userData);
+
+        /// <summary>
+        /// Subscribes trigger to process sources pushed from video identified by @a videoStreamId.
+        /// </summary>
+        internal void InvokeAddSource(SurveillanceSource source, SurveillanceEngineConfiguration config)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException(nameof(source));
+            }
+            SubscribeEventTrigger(Handle, source.StreamId, EngineConfiguration.GetHandle(config),
+                OnEventDetected).Validate("Failed to subscribe trigger");
+        }
+
+        /// <summary>
+        /// Removes the source from <see cref="SurveillanceEngine"/>.
+        /// </summary>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException">The <see cref="SurveillanceEngine"/> has already been disposed of.</exception>
+        /// <exception cref="ArgumentException"><paramref name="source"/> has not been added.</exception>
+        public void RemoveSource(SurveillanceSource source)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException(nameof(source));
+            }
+            UnsubscribeEventTrigger(Handle, source.StreamId).Validate("Failed to unsubscribe event trigger");
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_disposed)
+            {
+                return;
+            }
+
+            EventTriggerDestroy(_handle);
+            _disposed = true;
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/MediaVision/SurveillanceEngineConfiguration.cs b/src/Tizen.Multimedia/MediaVision/SurveillanceEngineConfiguration.cs
deleted file mode 100755 (executable)
index f167cac..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents concrete EngineConfig for creation of video surveillance systems.
-    /// </summary>
-    public class SurveillanceEngineConfiguration : EngineConfiguration
-    {
-        private const string _faceRecognitionModelFilePathKey = "MV_SURVEILLANCE_FACE_RECOGNITION_MODEL_FILE_PATH";
-        private const string _movementDetectionThresholdKey = "MV_SURVEILLANCE_MOVEMENT_DETECTION_THRESHOLD";
-        private const string _skipFramesCountKey = "MV_SURVEILLANCE_SKIP_FRAMES_COUNT";
-        private string _faceRecognitionModelFilePathValue;
-        private int _movementDetectionThresholdValue = 10;
-        private int _skipFramesCountValue = 0;
-
-        /// <summary>
-        /// The default constructor of SurveillanceEngineConfiguration class
-        /// </summary>
-        /// <code>
-        /// 
-        /// </code>
-        public SurveillanceEngineConfiguration()
-            : base()
-        {
-            FaceRecognitionModelFilePath = _faceRecognitionModelFilePathValue;
-            MovementDetectionThreshold = _movementDetectionThresholdValue;
-            SkipFramesCount = _skipFramesCountValue;
-        }
-
-        /// <summary>
-        /// Sets and gets face recognition model file path.\n
-        /// This value HAS TO BE set in engine configuration before subscribing on PersonRecognized event trigger.
-        /// </summary>
-        public string FaceRecognitionModelFilePath
-        {
-            get
-            {
-                return _faceRecognitionModelFilePathValue;
-            }
-
-            set
-            {
-                Add<string>(_faceRecognitionModelFilePathKey, value);
-                _faceRecognitionModelFilePathValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets movement detection threshold.\n
-        /// This value might be set in engine configuration before subscription on MovementDetected event trigger to specify sensitivity of the movement
-        /// detector. This value has to be integer in 0..255 range where 255 means that no movements will be detected, and 0 means that all frame changes
-        /// will be interpreted as movements. Default value is 10.
-        /// </summary>
-        public int MovementDetectionThreshold
-        {
-            get
-            {
-                return _movementDetectionThresholdValue;
-            }
-
-            set
-            {
-                if (value < 0 || value > 255)
-                {
-                    throw new ArgumentException("Invalid value");
-                }
-
-                Add<int>(_movementDetectionThresholdKey, value);
-                _movementDetectionThresholdValue = value;
-            }
-        }
-
-        /// <summary>
-        /// Sets and gets how many frames will be skipped during push source.\n
-        /// This integer value might be set in engine configuration to specify number of PushSource() function calls will be ignored by subscription
-        /// of the event trigger. Default value is 0. It means that no frames will be skipped and all mv_surveillance_push_source() function calls will
-        /// be processed.
-        /// </summary>
-        public int SkipFramesCount
-        {
-            get
-            {
-                return _skipFramesCountValue;
-            }
-
-            set
-            {
-                Add<int>(_skipFramesCountKey, value);
-                _skipFramesCountValue = value;
-            }
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/SurveillanceEventTrigger.cs b/src/Tizen.Multimedia/MediaVision/SurveillanceEventTrigger.cs
deleted file mode 100755 (executable)
index 04d1684..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using static Interop.MediaVision;
-
-namespace Tizen.Multimedia
-{
-    /// <summary>
-    /// This class represents an abstract Surveillance Event Trigger.
-    /// Media Vision Surveillance provides functionality can be utilized for creation of video surveillance systems.
-    /// The main idea underlying surveillance is event subscription model. These events can be added to the concrete
-    /// surveillance vent trigger classes.
-    /// </summary>
-    public abstract class SurveillanceEventTrigger : IDisposable
-    {
-        internal const string MovementDetectedType = "MV_SURVEILLANCE_EVENT_MOVEMENT_DETECTED";
-        internal const string PersonAppearanceChangedType = "MV_SURVEILLANCE_EVENT_PERSON_APPEARED_DISAPEARED";
-        internal const string PersonRecognizedType = "MV_SURVEILLANCE_EVENT_PERSON_RECOGNIZED";
-
-        private const string _movementNumberOfRegionsKey = "NUMBER_OF_MOVEMENT_REGIONS";
-        private const string _movementRegionsKey = "MOVEMENT_REGIONS";
-
-        private const string _personsRecognizedNumberKey = "NUMBER_OF_PERSONS";
-        private const string _personsRecognizedLocationsKey = "PERSONS_LOCATIONS";
-        private const string _personsRecognizedLabelsKey = "PERSONS_LABELS";
-        private const string _personsRecognizedConfidencesKey = "PERSONS_CONFIDENCES";
-
-        private const string _personsAppearedNumber = "NUMBER_OF_APPEARED_PERSONS";
-        private const string _personsDisappearedNumber = "NUMBER_OF_DISAPPEARED_PERSONS";
-        private const string _personsTrackedNumber = "NUMBER_OF_TRACKED_PERSONS";
-        private const string _personsAppearedLocations = "APPEARED_PERSONS_LOCATIONS";
-        private const string _personsDisappearedLocations = "DISAPPEARED_PERSONS_LOCATIONS";
-        private const string _personsTrackedLocations = "TRACKED_PERSONS_LOCATIONS";
-
-        internal IntPtr _eventTriggerHandle = IntPtr.Zero;
-        private string _eventTriggerType;
-        private bool _disposed = false;
-
-        internal event EventHandler<PersonRecognizedEventArgs> PersonRecognizedEvent;
-        internal event EventHandler<PersonAppearanceChangedEventArgs> PersonAppearanceChangedEvent;
-        internal event EventHandler<MovementDetectedEventArgs> MovementDetectedEvent;
-
-        private Interop.MediaVision.Surveillance.MvSurveillanceEventOccurredCallback eventOccurredCb;
-
-        /// <summary>
-        /// Constructor of the SurveillanceEventTrigger class.
-        /// </summary>
-        /// <param name="eventType">The type of the event trigger</param>
-        internal SurveillanceEventTrigger(string eventType)
-        {
-            _eventTriggerType = eventType;
-            int ret = Interop.MediaVision.Surveillance.EventTriggerCreate(eventType, out _eventTriggerHandle);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to create surveillance event trigger.");
-        }
-
-        /// <summary>
-        /// Destructor of the SurveillanceEventTrigger class.
-        /// </summary>
-        ~SurveillanceEventTrigger()
-        {
-            Dispose(false);
-        }
-
-        /// <summary>
-        /// Sets and gets ROI (Region Of Interest) to the event trigger
-        /// </summary>
-        public List<Point> Roi
-        {
-            get
-            {
-                int count;
-                IntPtr roiPtr;
-                int ret = Interop.MediaVision.Surveillance.GetEventTriggerRoi(_eventTriggerHandle, out count, out roiPtr);
-                if (ret != 0)
-                {
-                    Tizen.Log.Error(MediaVisionLog.Tag, "Failed to get roi");
-                    return null;
-                }
-
-                IntPtr[] pointsPtr = new IntPtr[count];
-                Marshal.Copy(roiPtr, pointsPtr, 0, count);
-
-                List<Point> points = new List<Point>();
-                for (int i = 0; i < count; i++)
-                {
-                    Interop.MediaVision.Point roi = (Interop.MediaVision.Point)Marshal.PtrToStructure(pointsPtr[i], typeof(Interop.MediaVision.Point));
-                    points.Add(new Point()
-                    {
-                        X = roi.x,
-                        Y = roi.y
-                    });
-                }
-
-                return points;
-            }
-
-            set
-            {
-                if (value.Count == 0)
-                {
-                    throw new ArgumentException("Invalid array");
-                }
-
-                IntPtr[] ptrArray = new IntPtr[value.Count];
-                for (int i = 0; i < value.Count; i++)
-                {
-                    Interop.MediaVision.Point point = new Interop.MediaVision.Point()
-                    {
-                        x = value[i].X,
-                        y = value[i].Y
-                    };
-
-                    IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(point));
-                    Marshal.StructureToPtr(point, ptr, false);
-                    ptrArray[i] = ptr;
-                }
-
-                int size = Marshal.SizeOf(typeof(IntPtr)) * ptrArray.Length;
-                IntPtr roiPtr = Marshal.AllocHGlobal(size);
-                Marshal.Copy(ptrArray, 0, roiPtr, ptrArray.Length);
-
-                int ret = Interop.MediaVision.Surveillance.SetEventTriggerRoi(_eventTriggerHandle, value.Count, roiPtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to set roi");
-            }
-        }
-
-        /// <summary>
-        /// Subscribes trigger to process sources pushed from video identified by @a videoStreamId.
-        /// </summary>
-        /// <param name="videoStreamId">The identifier of the video stream for which event trigger activation will be checked</param>
-        /// <param name="config">The engine configuration of the event</param>
-        /// <code>
-        ///
-        /// </code>
-        public void Subscribe(int videoStreamId, SurveillanceEngineConfiguration config = null)
-        {
-            eventOccurredCb = (IntPtr trigger, IntPtr source, int streamId, IntPtr eventResult, IntPtr userData) =>
-            {
-                Tizen.Log.Info(MediaVisionLog.Tag, string.Format("Surveillance event occurred, video stream id : {0}", streamId));
-                if (eventResult != null)
-                {
-                    if (string.Equals(_eventTriggerType, MovementDetectedType))
-                    {
-                        MovementDetectedEventArgs e = GetMovementDetectedEventArgs(eventResult, streamId);
-                        MovementDetectedEvent?.Invoke(null, e);
-                    }
-                    else if (string.Equals(_eventTriggerType, PersonRecognizedType))
-                    {
-                        PersonRecognizedEventArgs e = GetPersonRecognizedEventArgs(eventResult, streamId);
-                        PersonRecognizedEvent?.Invoke(null, e);
-                    }
-                    else if (string.Equals(_eventTriggerType, PersonAppearanceChangedType))
-                    {
-                        PersonAppearanceChangedEventArgs e = GetPersonAppearanceChangedEventArgs(eventResult, streamId);
-                        PersonAppearanceChangedEvent?.Invoke(null, e);
-                    }
-                }
-            };
-
-            int ret = Interop.MediaVision.Surveillance.SubscribeEventTrigger(_eventTriggerHandle, videoStreamId, (config != null) ? config._engineHandle : IntPtr.Zero, eventOccurredCb, IntPtr.Zero);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to subscribe trigger");
-        }
-
-        /// <summary>
-        /// Unsubscribes trigger from the event
-        /// </summary>
-        /// <param name="videoStreamId">The identifier of the video source for which subscription will be stopped</param>
-        /// <code>
-        ///
-        /// </code>
-        public void Unsubscribe(int videoStreamId)
-        {
-            int ret = Interop.MediaVision.Surveillance.UnsubscribeEventTrigger(_eventTriggerHandle, videoStreamId);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to unsubscribe event trigger");
-        }
-
-        /// <summary>
-        /// Pushes source to the surveillance system to detect events.
-        /// </summary>
-        /// <param name="source">The media source</param>
-        /// <param name="videoStreamId">The identifier of video stream from which @a source is coming</param>
-        /// <code>
-        ///
-        /// </code>
-        public void PushSource(MediaVisionSource source, int videoStreamId)
-        {
-            if (source == null)
-            {
-                throw new ArgumentException("Invalid source");
-            }
-
-            int ret = Interop.MediaVision.Surveillance.PushSource(source._sourceHandle, videoStreamId);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to push source");
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if (_disposed)
-            {
-                return;
-            }
-
-            if (disposing)
-            {
-                // Free managed objects
-            }
-
-            Interop.MediaVision.Surveillance.EventTriggerDestroy(_eventTriggerHandle);
-            _disposed = true;
-        }
-
-        private MovementDetectedEventArgs GetMovementDetectedEventArgs(IntPtr handle, int videoStreamId)
-        {
-            int count;
-            IntPtr resultPtr = IntPtr.Zero;
-            List<Rectangle> regions = new List<Rectangle>();
-
-            int ret = Interop.MediaVision.Surveillance.GetResultCount(handle, _movementNumberOfRegionsKey, out count);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result count");
-
-            if (count > 0)
-            {
-                resultPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)) * count);
-                ret = Interop.MediaVision.Surveillance.GetResultValue(handle, _movementRegionsKey, resultPtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result");
-
-                for (int i = 0; i < count; i++)
-                {
-                    Interop.MediaVision.Rectangle rect = (Interop.MediaVision.Rectangle)Marshal.PtrToStructure(resultPtr, typeof(Interop.MediaVision.Rectangle));
-                    regions.Add(new Rectangle()
-                    {
-                        Point = new Point()
-                        {
-                            X = rect.x,
-                            Y = rect.y
-                        },
-                        Width = rect.width,
-                        Height = rect.height
-                    });
-                    resultPtr = IntPtr.Add(resultPtr, Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)));
-                }
-            }
-
-            MovementDetectedEventArgs e = new MovementDetectedEventArgs()
-            {
-                VideoStreamId = videoStreamId,
-                Regions = regions
-            };
-
-            return e;
-        }
-
-        private PersonRecognizedEventArgs GetPersonRecognizedEventArgs(IntPtr handle, int videoStreamId)
-        {
-            int count;
-            List<PersonRecognitionResult> result = new List<PersonRecognitionResult>();
-
-            int ret = Interop.MediaVision.Surveillance.GetResultCount(handle, _personsRecognizedNumberKey, out count);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result count");
-
-            if (count > 0)
-            {
-                IntPtr locationPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)) * count);
-                ret = Interop.MediaVision.Surveillance.GetResultValue(handle, _personsRecognizedLocationsKey, locationPtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get location");
-
-                IntPtr labelPtr = Marshal.AllocHGlobal(sizeof(int) * count);
-                ret = Interop.MediaVision.Surveillance.GetResultValue(handle, _personsRecognizedLabelsKey, labelPtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get label");
-                int[] labelsArray = new int[count];
-                Marshal.Copy(labelPtr, labelsArray, 0, count);
-
-                IntPtr confidencePtr = Marshal.AllocHGlobal(sizeof(double) * count);
-                ret = Interop.MediaVision.Surveillance.GetResultValue(handle, _personsRecognizedConfidencesKey, confidencePtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get confidence");
-                double[] confidencesArray = new double[count];
-                Marshal.Copy(confidencePtr, confidencesArray, 0, count);
-
-                for (int i = 0; i < count; i++)
-                {
-                    Interop.MediaVision.Rectangle rect = (Interop.MediaVision.Rectangle)Marshal.PtrToStructure(locationPtr, typeof(Interop.MediaVision.Rectangle));
-                    Rectangle location = new Rectangle()
-                    {
-                        Point = new Point()
-                        {
-                            X = rect.x,
-                            Y = rect.y
-                        },
-                        Width = rect.width,
-                        Height = rect.height
-                    };
-
-                    result.Add(new PersonRecognitionResult()
-                    {
-                        Location = location,
-                        Label = labelsArray[i],
-                        Confidence = confidencesArray[i]
-                    });
-
-                    locationPtr = IntPtr.Add(locationPtr, Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)));
-                }
-            }
-
-            PersonRecognizedEventArgs e = new PersonRecognizedEventArgs()
-            {
-                VideoStreamId = videoStreamId,
-                Result = result
-            };
-
-            return e;
-        }
-
-        private PersonAppearanceChangedEventArgs GetPersonAppearanceChangedEventArgs(IntPtr handle, int videoStreamId)
-        {
-            int numOfAppearedPersons, numOfDisappearedPersons, numOfTrackedPersons;
-
-            List<Rectangle> appearedLocations = new List<Rectangle>();
-            List<Rectangle> disappearedLocations = new List<Rectangle>();
-            List<Rectangle> trackedLocations = new List<Rectangle>();
-
-            int ret = Interop.MediaVision.Surveillance.GetResultCount(handle, _personsAppearedNumber, out numOfAppearedPersons);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result");
-
-            if (numOfAppearedPersons > 0)
-            {
-                IntPtr appearedLocationPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)) * numOfAppearedPersons);
-                ret = Interop.MediaVision.Surveillance.GetResultValue(handle, _personsAppearedLocations, appearedLocationPtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result");
-
-                for (int i = 0; i < numOfAppearedPersons; i++)
-                {
-                    Interop.MediaVision.Rectangle rect = (Interop.MediaVision.Rectangle)Marshal.PtrToStructure(appearedLocationPtr, typeof(Interop.MediaVision.Rectangle));
-                    appearedLocations.Add(new Rectangle()
-                    {
-                        Point = new Point()
-                        {
-                            X = rect.x,
-                            Y = rect.y
-                        },
-                        Width = rect.width,
-                        Height = rect.height
-                    });
-
-                    appearedLocationPtr = IntPtr.Add(appearedLocationPtr, Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)));
-                }
-            }
-
-            ret = Interop.MediaVision.Surveillance.GetResultCount(handle, _personsDisappearedNumber, out numOfDisappearedPersons);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result");
-
-            if (numOfDisappearedPersons > 0)
-            {
-                IntPtr disAppearedLocationPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)) * numOfDisappearedPersons);
-                ret = Interop.MediaVision.Surveillance.GetResultValue(handle, _personsDisappearedLocations, disAppearedLocationPtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result");
-
-                for (int i = 0; i < numOfDisappearedPersons; i++)
-                {
-                    Interop.MediaVision.Rectangle rect = (Interop.MediaVision.Rectangle)Marshal.PtrToStructure(disAppearedLocationPtr, typeof(Interop.MediaVision.Rectangle));
-                    disappearedLocations.Add(new Rectangle()
-                    {
-                        Point = new Point()
-                        {
-                            X = rect.x,
-                            Y = rect.y
-                        },
-                        Width = rect.width,
-                        Height = rect.height
-                    });
-
-                    disAppearedLocationPtr = IntPtr.Add(disAppearedLocationPtr, Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)));
-                }
-            }
-
-            ret = Interop.MediaVision.Surveillance.GetResultCount(handle, _personsTrackedNumber, out numOfTrackedPersons);
-            MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result");
-
-            if (numOfTrackedPersons > 0)
-            {
-                IntPtr trackedLocationPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)) * numOfTrackedPersons);
-                ret = Interop.MediaVision.Surveillance.GetResultValue(handle, _personsTrackedLocations, trackedLocationPtr);
-                MediaVisionErrorFactory.CheckAndThrowException(ret, "Failed to get result");
-
-                for (int i = 0; i < numOfTrackedPersons; i++)
-                {
-                    Interop.MediaVision.Rectangle rect = (Interop.MediaVision.Rectangle)Marshal.PtrToStructure(trackedLocationPtr, typeof(Interop.MediaVision.Rectangle));
-                    trackedLocations.Add(new Rectangle()
-                    {
-                        Point = new Point()
-                        {
-                            X = rect.x,
-                            Y = rect.y
-                        },
-                        Width = rect.width,
-                        Height = rect.height
-                    });
-
-                    trackedLocationPtr = IntPtr.Add(trackedLocationPtr, Marshal.SizeOf(typeof(Interop.MediaVision.Rectangle)));
-                }
-            }
-
-            PersonAppearanceChangedEventArgs e = new PersonAppearanceChangedEventArgs()
-            {
-                VideoStreamId = videoStreamId,
-                AppearedLocations = appearedLocations,
-                DisappearedLocations = disappearedLocations,
-                TrackedLocations = trackedLocations
-            };
-
-            return e;
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia/MediaVision/SurveillanceSource.cs b/src/Tizen.Multimedia/MediaVision/SurveillanceSource.cs
new file mode 100644 (file)
index 0000000..bd9c314
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using static Interop.MediaVision.Surveillance;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Provides the ability to push source to surveillance engines.
+    /// </summary>
+    /// <seealso cref="MovementDetector"/>
+    /// <seealso cref="PersonAppearanceDetector"/>
+    /// <seealso cref="PersonRecognizer"/>
+    public class SurveillanceSource
+    {
+        private static int _nextStreamId = int.MinValue;
+
+        private static int GetNextStreamId()
+        {
+            if (_nextStreamId == int.MaxValue)
+            {
+                return _nextStreamId = int.MinValue;
+            }
+            return _nextStreamId++;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SurveillanceSource"/> class.
+        /// </summary>
+        public SurveillanceSource()
+        {
+            StreamId = GetNextStreamId();
+        }
+
+        /// <summary>
+        /// Pushes source to the surveillance system to detect events.
+        /// </summary>
+        /// <param name="source">The media source used for surveillance.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception>
+        /// <exception cref="InvalidOperationException">This <see cref="SurveillanceSource"/> has not been added yet.</exception>
+        /// <seealso cref="MovementDetector.AddSource(SurveillanceSource)"/>
+        /// <seealso cref="MovementDetector.AddSource(SurveillanceSource, MovementDetectionConfiguration)"/>
+        /// <seealso cref="PersonAppearanceDetector.AddSource(SurveillanceSource)"/>
+        /// <seealso cref="PersonAppearanceDetector.AddSource(SurveillanceSource, PersonAppearanceDetectionConfiguration)"/>
+        /// <seealso cref="PersonRecognizer.AddSource(SurveillanceSource, PersonRecognitionConfiguration)"/>
+        public void Push(MediaVisionSource source)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException(nameof(source));
+            }
+
+            PushSource(source.Handle, StreamId).Validate("Failed to push source");
+        }
+
+        internal int StreamId { get; }
+    }
+}