2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Diagnostics;
19 using System.Runtime.InteropServices;
20 using System.Threading;
21 using Tizen.Internals.Errors;
23 namespace Tizen.Multimedia
26 /// Represents a packet for multimedia.
28 public abstract partial class MediaPacket : IDisposable
30 private IntPtr _handle = IntPtr.Zero;
33 /// Initializes a new instance of the MediaPacket class with the specified media format.
35 /// <param name="format">The media format containing properties for the packet.</param>
36 /// <exception cref="ArgumentNullException">format is null.</exception>
37 /// <exception cref="ArgumentException">
38 /// <see cref="MediaFormatType"/> of the specified format is <see cref="MediaFormatType.Container"/>.</exception>
39 /// <exception cref="InvalidOperationException">Operation failed.</exception>
40 internal MediaPacket(MediaFormat format)
44 throw new ArgumentNullException(nameof(format));
47 if (format.Type == MediaFormatType.Container)
49 throw new ArgumentException("Container format can't be used to create a new packet.");
57 /// Initializes a new instance of the MediaPacket class from a native handle.
59 /// <param name="handle">The native handle to be used.</param>
60 internal MediaPacket(IntPtr handle)
65 int ret = Interop.MediaPacket.GetFormat(handle, out formatHandle);
67 MultimediaDebug.AssertNoError(ret);
71 if (formatHandle != IntPtr.Zero)
73 _format = MediaFormat.FromHandle(formatHandle);
78 Interop.MediaFormat.Unref(formatHandle);
88 /// Creates and initializes a native handle for the current object.
90 /// <param name="format">The format to be set to the media format.</param>
91 /// <exception cref="InvalidOperationException">Operation failed.</exception>
92 private void Initialize(MediaFormat format)
94 if (format.Type == MediaFormatType.Container)
96 throw new ArgumentException("Creating a packet for container is not supported.");
99 IntPtr formatHandle = IntPtr.Zero;
103 formatHandle = format.AsNativeHandle();
105 int ret = Interop.MediaPacket.Create(formatHandle, IntPtr.Zero, IntPtr.Zero, out _handle);
106 MultimediaDebug.AssertNoError(ret);
108 Debug.Assert(_handle != IntPtr.Zero, "Created handle must not be null");
114 if (_handle != IntPtr.Zero)
116 Interop.MediaPacket.Destroy(_handle);
117 _handle = IntPtr.Zero;
124 if (formatHandle != IntPtr.Zero)
126 Interop.MediaFormat.Unref(formatHandle);
132 /// Allocates internal buffer.
134 /// <exception cref="InvalidOperationException">Operation failed.</exception>
137 ErrorCode ret = (ErrorCode)Interop.MediaPacket.Alloc(_handle);
138 if (ret == ErrorCode.None)
145 case ErrorCode.OutOfMemory:
146 throw new OutOfMemoryException("Failed to allocate buffer for the packet.");
149 throw new InvalidOperationException("Failed to create a packet.");
154 private readonly MediaFormat _format;
157 /// Gets the media format of the current packet.
159 public MediaFormat Format
163 ValidateNotDisposed();
169 /// Gets or sets the PTS(Presentation Time Stamp) value of the current packet.
171 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed.</exception>
172 /// <exception cref="InvalidOperationException">
173 /// The MediaPacket is not writable state which means it being used by another module.</exception>
178 ValidateNotDisposed();
181 int ret = Interop.MediaPacket.GetPts(_handle, out value);
183 MultimediaDebug.AssertNoError(ret);
189 ValidateNotDisposed();
192 int ret = Interop.MediaPacket.SetPts(_handle, value);
194 MultimediaDebug.AssertNoError(ret);
199 /// Gets or sets the DTS(Decoding Time Stamp) value of the current packet.
201 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed.</exception>
202 /// <exception cref="InvalidOperationException">
203 /// The MediaPacket is not in writable state which means it being used by another module.</exception>
208 ValidateNotDisposed();
211 int ret = Interop.MediaPacket.GetDts(_handle, out value);
213 MultimediaDebug.AssertNoError(ret);
219 ValidateNotDisposed();
222 int ret = Interop.MediaPacket.SetDts(_handle, value);
224 MultimediaDebug.AssertNoError(ret);
229 /// Gets a value indicating whether the packet is encoded type.
231 /// <value>true if the packet is encoded type; otherwise, false.</value>
232 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed.</exception>
233 public bool IsEncoded
237 ValidateNotDisposed();
240 int ret = Interop.MediaPacket.IsEncoded(_handle, out value);
242 MultimediaDebug.AssertNoError(ret);
248 private MediaPacketBuffer _buffer;
251 /// Gets the buffer of the packet.
253 /// <value>The <see cref="MediaPacketBuffer"/> allocated to the packet.
254 /// This property will return null if the packet is raw video format.</value>
255 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed.</exception>
256 /// <seealso cref="IsEncoded"/>
257 /// <seealso cref="VideoPlanes"/>
258 public MediaPacketBuffer Buffer
262 ValidateNotDisposed();
264 if (IsVideoPlaneSupported)
271 _buffer = GetBuffer();
279 /// Gets or sets a length of data written in the <see cref="Buffer"/>.
281 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed.</exception>
282 /// <exception cref="ArgumentOutOfRangeException">
283 /// The value specified for this property is less than zero or greater than <see cref="MediaPacketBuffer.Length"/>.</exception>
284 /// <exception cref="InvalidOperationException">
285 /// The MediaPacket has <see cref="VideoPlanes"/> instead of <see cref="Buffer"/>.\n
287 /// The MediaPacket is not in writable state which means it being used by another module.
289 public int BufferWrittenLength
293 ValidateNotDisposed();
296 int ret = Interop.MediaPacket.GetBufferSize(_handle, out value);
297 MultimediaDebug.AssertNoError(ret);
299 Debug.Assert(value < int.MaxValue);
305 ValidateNotDisposed();
308 if (IsVideoPlaneSupported)
310 throw new InvalidOperationException(
311 "This packet uses VideoPlanes instead of Buffer.");
314 Debug.Assert(Buffer != null);
316 if (value < 0 || value >= Buffer.Length)
318 throw new ArgumentOutOfRangeException("value must be less than Buffer.Size.");
321 int ret = Interop.MediaPacket.SetBufferSize(_handle, (ulong)value);
322 MultimediaDebug.AssertNoError(ret);
326 private MediaPacketVideoPlane[] _videoPlanes;
329 /// Gets the video planes of the packet.
331 /// <value>The <see cref="MediaPacketVideoPlane"/>s allocated to the packet.
332 /// This property will return null if the packet is not raw video format.</value>
333 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed.</exception>
334 /// <seealso cref="IsEncoded"/>
335 /// <seealso cref="Buffer"/>
336 public MediaPacketVideoPlane[] VideoPlanes
340 ValidateNotDisposed();
342 if (!IsVideoPlaneSupported)
347 if (_videoPlanes == null)
349 _videoPlanes = GetVideoPlanes();
357 /// Gets or sets the buffer flags of the packet.
359 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed.</exception>
360 /// <exception cref="InvalidOperationException">
361 /// The MediaPacket is not in writable state which means it being used by another module.
363 public MediaPacketBufferFlags BufferFlags
367 ValidateNotDisposed();
371 int ret = Interop.MediaPacket.GetBufferFlags(_handle, out value);
373 MultimediaDebug.AssertNoError(ret);
375 return (MediaPacketBufferFlags)value;
380 ValidateNotDisposed();
383 int ret = Interop.MediaPacket.ResetBufferFlags(_handle);
385 MultimediaDebug.AssertNoError(ret);
387 ret = Interop.MediaPacket.SetBufferFlags(_handle, (int)value);
389 MultimediaDebug.AssertNoError(ret);
394 /// Gets a value indicating whether the packet has been disposed of.
396 /// <value>true if the packet has been disposed of; otherwise, false.</value>
397 public bool IsDisposed
405 private bool _isDisposed = false;
409 /// Releases all resources used by the <see cref="MediaPacket"/> object.
411 /// <exception cref="InvalidOperationException">
412 /// The MediaPacket can not be disposed which means it being used by another module.
414 public void Dispose()
423 GC.SuppressFinalize(this);
427 /// Releases the resources used by the <see cref="MediaPacket"/> object.
429 /// <param name="disposing">
430 /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
432 protected virtual void Dispose(bool disposing)
439 if (_handle != IntPtr.Zero)
441 Interop.MediaPacket.Destroy(_handle);
442 _handle = IntPtr.Zero;
448 internal IntPtr GetHandle()
450 ValidateNotDisposed();
452 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
458 /// Validate the current object has not been disposed of.
460 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
461 private void ValidateNotDisposed()
465 throw new ObjectDisposedException("This packet has already been disposed of.");
470 /// Ensures whether the packet is writable.
472 /// <exception cref="ObjectDisposedException">The MediaPacket already has been disposed of.</exception>
473 /// <exception cref="InvalidOperationException">The MediaPacket is being used by another module.</exception>
474 internal void EnsureWritableState()
476 ValidateNotDisposed();
481 /// Ensures whether the packet is readable.
483 /// <exception cref="ObjectDisposedException">The MediaPacket already has been disposed of.</exception>
484 internal void EnsureReadableState()
486 ValidateNotDisposed();
490 /// Gets a value indicating whether the packet is raw video format.
492 /// <value>true if the packet is raw video format; otherwise, false.</value>
493 private bool IsVideoPlaneSupported
497 return !IsEncoded && Format.Type == MediaFormatType.Video;
502 /// Retrieves video planes of the current packet.
504 /// <returns>The <see cref="MediaPacketVideoPlane"/>s allocated to the current MediaPacket.</returns>
505 private MediaPacketVideoPlane[] GetVideoPlanes()
507 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
509 uint numberOfPlanes = 0;
510 int ret = Interop.MediaPacket.GetNumberOfVideoPlanes(_handle, out numberOfPlanes);
512 MultimediaDebug.AssertNoError(ret);
514 MediaPacketVideoPlane[] planes = new MediaPacketVideoPlane[numberOfPlanes];
516 for (int i = 0; i < numberOfPlanes; ++i)
518 planes[i] = new MediaPacketVideoPlane(this, i);
525 /// Retrieves the buffer of the current packet.
527 /// <returns>The <see cref="MediaPacketBuffer"/> allocated to the current MediaPacket.</returns>
528 private MediaPacketBuffer GetBuffer()
530 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
534 int ret = Interop.MediaPacket.GetBufferData(_handle, out dataHandle);
535 MultimediaDebug.AssertNoError(ret);
537 Debug.Assert(dataHandle != IntPtr.Zero, "Data handle is invalid!");
540 ret = Interop.MediaPacket.GetAllocatedBufferSize(_handle, out size);
541 MultimediaDebug.AssertNoError(ret);
543 return new MediaPacketBuffer(this, dataHandle, size);
547 /// Creates an object of the MediaPacket with the specified <see cref="MediaFormat"/>.
549 /// <param name="format">The media format for the new packet.</param>
550 /// <returns>A new MediaPacket object.</returns>
551 public static MediaPacket Create(MediaFormat format)
553 return new SimpleMediaPacket(format);
556 internal static MediaPacket From(IntPtr handle)
558 return new SimpleMediaPacket(handle);
562 internal class SimpleMediaPacket : MediaPacket
564 internal SimpleMediaPacket(MediaFormat format) : base(format)
568 internal SimpleMediaPacket(IntPtr handle) : base(handle)