Release 4.0.0-preview1-00201
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia / MediaTool / MediaPacketBuffer.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Diagnostics;
19 using System.Runtime.InteropServices;
20
21 namespace Tizen.Multimedia
22 {
23     /// <summary>
24     /// Represents a buffer for a <see cref="MediaPacket"/>.
25     /// </summary>
26     public class MediaPacketBuffer
27     {
28         private readonly MediaPacket _packet;
29         private readonly IntPtr _dataHandle;
30
31         internal MediaPacketBuffer(MediaPacket packet, IntPtr dataHandle, int size)
32         {
33             Debug.Assert(packet != null, "Packet is null!");
34             Debug.Assert(!packet.IsDisposed, "Packet is already disposed!");
35             Debug.Assert(dataHandle != IntPtr.Zero, "dataHandle is null!");
36             Debug.Assert(size >= 0, "size must not be negative!");
37
38             _packet = packet;
39             _dataHandle = dataHandle;
40             _length = size;
41         }
42
43         /// <summary>
44         /// Gets or sets a value at the specified index.
45         /// </summary>
46         /// <param name="index">The index of the value to get or set.</param>
47         /// <exception cref="ArgumentOutOfRangeException">
48         ///     <paramref name="index"/> is less than zero.\n
49         ///     -or-\n
50         ///     <paramref name="index"/> is equal to or greater than <see cref="Length"/>.
51         /// </exception>
52         /// <exception cref="ObjectDisposedException">The MediaPacket that owns the current buffer has already been disposed of.</exception>
53         /// <exception cref="InvalidOperationException">The MediaPacket that owns the current buffer is being used by another module.</exception>
54         public byte this[int index]
55         {
56             get
57             {
58                 _packet.EnsureReadableState();
59
60                 if (index < 0 || index >= Length)
61                 {
62                     throw new ArgumentOutOfRangeException($"Valid index range is [0, { nameof(Length) }).");
63                 }
64
65                 return Marshal.ReadByte(_dataHandle, index);
66             }
67             set
68             {
69                 _packet.EnsureWritableState();
70
71                 Marshal.WriteByte(_dataHandle, index, value);
72             }
73         }
74
75         /// <summary>
76         /// Validates the range.
77         /// </summary>
78         /// <param name="offset"></param>
79         /// <param name="length"></param>
80         /// <exception cref="ArgumentOutOfRangeException">
81         ///     <paramref name="offset"/> + <paramref name="length"/> is greater than <see cref="Length"/>.\n
82         ///     -or-\n
83         ///     <paramref name="offset"/> or <paramref name="length"/> is less than zero.
84         /// </exception>
85         private void ValidateRange(int offset, int length)
86         {
87             if (offset + length > _length)
88             {
89                 throw new ArgumentOutOfRangeException("offset + length can't be greater than length of the buffer.");
90             }
91             if (length < 0)
92             {
93                 throw new ArgumentOutOfRangeException($"Length can't be less than zero : { length }.");
94             }
95             if (offset < 0)
96             {
97                 throw new ArgumentOutOfRangeException($"Offset can't be less than zero : { offset }.");
98             }
99         }
100
101         /// <summary>
102         /// Copies the data from a byte array to the buffer.
103         /// </summary>
104         /// <param name="source">The array to copy from.</param>
105         /// <param name="startIndex">The zero-based index in the source array where copying should start.</param>
106         /// <param name="length">The number of array elements to copy.</param>
107         /// <param name="offset">The zero-based index in the buffer where copying should start.</param>
108         /// <exception cref="ArgumentOutOfRangeException">
109         ///     <paramref name="startIndex"/>, <paramref name="offset"/>, or <paramref name="length"/> is not valid.
110         /// </exception>
111         /// <exception cref="ObjectDisposedException">The MediaPacket that owns the current buffer has already been disposed of.</exception>
112         public void CopyFrom(byte[] source, int startIndex, int length, int offset = 0)
113         {
114             _packet.EnsureReadableState();
115
116             if (startIndex < 0)
117             {
118                 throw new ArgumentOutOfRangeException("startIndex can't be less than zero.");
119             }
120             if (startIndex + length > source.Length)
121             {
122                 throw new ArgumentOutOfRangeException("startIndex + length can't be greater than source.Length.");
123             }
124
125             ValidateRange(offset, length);
126
127             Marshal.Copy(source, startIndex, IntPtr.Add(_dataHandle, offset), length);
128         }
129
130         /// <summary>
131         /// Copies the data from the buffer to a byte array.
132         /// </summary>
133         /// <param name="dest">The array to copy to.</param>
134         /// <param name="startIndex">The zero-based index in the destination array where copying should start.</param>
135         /// <param name="length">The number of elements to copy.</param>
136         /// <param name="offset">The zero-based index in the buffer where copying should start.</param>
137         /// <exception cref="ArgumentOutOfRangeException">
138         ///     <paramref name="startIndex"/>, <paramref name="offset"/>, <paramref name="length"/>, or <paramref name="offset"/> is not valid.
139         /// </exception>
140         /// <exception cref="ObjectDisposedException">The MediaPacket that owns the current buffer has already been disposed of.</exception>
141         /// <exception cref="InvalidOperationException">The MediaPacket that owns the current buffer is being used by another module.</exception>
142         public void CopyTo(byte[] dest, int startIndex, int length, int offset = 0)
143         {
144             _packet.EnsureWritableState();
145
146             if (startIndex < 0)
147             {
148                 throw new ArgumentOutOfRangeException("Start index can't be less than zero.");
149             }
150             if (startIndex + length > dest.Length)
151             {
152                 throw new ArgumentOutOfRangeException("startIndex + length can't be greater than dest.Length.");
153             }
154
155             ValidateRange(offset, length);
156
157             Marshal.Copy(IntPtr.Add(_dataHandle, offset), dest, startIndex, length);
158         }
159
160         private readonly int _length;
161
162         /// <summary>
163         /// Gets the size of the buffer, in bytes.
164         /// </summary>
165         /// <exception cref="ObjectDisposedException">The MediaPacket that owns the current buffer has already been disposed of.</exception>
166         public int Length
167         {
168             get
169             {
170                 _packet.EnsureReadableState();
171
172                 return _length;
173             }
174         }
175     }
176 }