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"><paramref name="format"/> is null.</exception>
37 /// <exception cref="ArgumentException">
38 /// The <see cref="MediaFormatType"/> of the specified format is <see cref="MediaFormatType.Container"/>.
40 /// <exception cref="InvalidOperationException">Operation failed.</exception>
41 internal MediaPacket(MediaFormat format)
45 throw new ArgumentNullException(nameof(format));
48 if (format.Type == MediaFormatType.Container)
50 throw new ArgumentException("Container format can't be used to create a new packet.");
58 /// Initializes a new instance of the MediaPacket class from a native handle.
60 /// <param name="handle">The native handle to be used.</param>
61 internal MediaPacket(IntPtr handle)
66 int ret = Interop.MediaPacket.GetFormat(handle, out formatHandle);
68 MultimediaDebug.AssertNoError(ret);
72 if (formatHandle != IntPtr.Zero)
74 _format = MediaFormat.FromHandle(formatHandle);
79 Interop.MediaFormat.Unref(formatHandle);
89 /// Creates and initializes a native handle for the current object.
91 /// <param name="format">The format to be set to the media format.</param>
92 /// <exception cref="InvalidOperationException">Operation failed.</exception>
93 private void Initialize(MediaFormat format)
95 if (format.Type == MediaFormatType.Container)
97 throw new ArgumentException("Creating a packet for container is not supported.");
100 IntPtr formatHandle = IntPtr.Zero;
104 formatHandle = format.AsNativeHandle();
106 int ret = Interop.MediaPacket.Create(formatHandle, IntPtr.Zero, IntPtr.Zero, out _handle);
107 MultimediaDebug.AssertNoError(ret);
109 Debug.Assert(_handle != IntPtr.Zero, "Created handle must not be null");
115 if (_handle != IntPtr.Zero)
117 Interop.MediaPacket.Destroy(_handle);
118 _handle = IntPtr.Zero;
125 if (formatHandle != IntPtr.Zero)
127 Interop.MediaFormat.Unref(formatHandle);
133 /// Allocates internal buffer.
135 /// <exception cref="InvalidOperationException">Operation failed.</exception>
138 ErrorCode ret = (ErrorCode)Interop.MediaPacket.Alloc(_handle);
139 if (ret == ErrorCode.None)
144 _handle = IntPtr.Zero;
148 case ErrorCode.OutOfMemory:
149 throw new OutOfMemoryException("Failed to allocate buffer for the packet.");
152 throw new InvalidOperationException("Failed to create a packet.");
157 private readonly MediaFormat _format;
160 /// Gets the media format of the current packet.
162 public MediaFormat Format
166 ValidateNotDisposed();
172 /// Gets or sets the PTS(Presentation Time Stamp) value of the current packet.
174 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
175 /// <exception cref="InvalidOperationException">
176 /// The MediaPacket is not in the writable state, which means it is being used by another module.
182 ValidateNotDisposed();
185 int ret = Interop.MediaPacket.GetPts(_handle, out value);
187 MultimediaDebug.AssertNoError(ret);
193 ValidateNotDisposed();
196 int ret = Interop.MediaPacket.SetPts(_handle, value);
198 MultimediaDebug.AssertNoError(ret);
203 /// Gets or sets the DTS(Decoding Time Stamp) value of the current packet.
205 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
206 /// <exception cref="InvalidOperationException">
207 /// The MediaPacket is not in the writable state, which means it is being used by another module.
213 ValidateNotDisposed();
216 int ret = Interop.MediaPacket.GetDts(_handle, out value);
218 MultimediaDebug.AssertNoError(ret);
224 ValidateNotDisposed();
227 int ret = Interop.MediaPacket.SetDts(_handle, value);
229 MultimediaDebug.AssertNoError(ret);
234 /// Gets a value indicating whether the packet is the encoded type.
236 /// <value>true if the packet is the encoded type; otherwise, false.</value>
237 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
238 public bool IsEncoded
242 ValidateNotDisposed();
245 int ret = Interop.MediaPacket.IsEncoded(_handle, out value);
247 MultimediaDebug.AssertNoError(ret);
253 private MediaPacketBuffer _buffer;
256 /// Gets the buffer of the packet.
258 /// <value>The <see cref="MediaPacketBuffer"/> allocated to the packet.
259 /// This property will return null if the packet is in the raw video format.</value>
260 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
261 /// <seealso cref="IsEncoded"/>
262 /// <seealso cref="VideoPlanes"/>
263 public MediaPacketBuffer Buffer
267 ValidateNotDisposed();
269 if (IsVideoPlaneSupported)
276 _buffer = GetBuffer();
284 /// Gets or sets a length of data written in the <see cref="Buffer"/>.
286 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
287 /// <exception cref="ArgumentOutOfRangeException">
288 /// The value specified for this property is less than zero or greater than <see cref="MediaPacketBuffer.Length"/>.</exception>
289 /// <exception cref="InvalidOperationException">
290 /// The MediaPacket has <see cref="VideoPlanes"/> instead of <see cref="Buffer"/>.\n
292 /// The MediaPacket is not in the writable state, which means it is being used by another module.
294 public int BufferWrittenLength
298 ValidateNotDisposed();
301 int ret = Interop.MediaPacket.GetBufferSize(_handle, out value);
302 MultimediaDebug.AssertNoError(ret);
304 Debug.Assert(value < int.MaxValue);
310 ValidateNotDisposed();
313 if (IsVideoPlaneSupported)
315 throw new InvalidOperationException(
316 "This packet uses VideoPlanes instead of Buffer.");
319 Debug.Assert(Buffer != null);
321 if (value < 0 || value >= Buffer.Length)
323 throw new ArgumentOutOfRangeException("value must be less than Buffer.Size.");
326 int ret = Interop.MediaPacket.SetBufferSize(_handle, (ulong)value);
327 MultimediaDebug.AssertNoError(ret);
331 private MediaPacketVideoPlane[] _videoPlanes;
334 /// Gets the video planes of the packet.
336 /// <value>The <see cref="MediaPacketVideoPlane"/>s allocated to the packet.
337 /// This property will return null if the packet is not in the raw video format.</value>
338 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
339 /// <seealso cref="IsEncoded"/>
340 /// <seealso cref="Buffer"/>
341 public MediaPacketVideoPlane[] VideoPlanes
345 ValidateNotDisposed();
347 if (!IsVideoPlaneSupported)
352 if (_videoPlanes == null)
354 _videoPlanes = GetVideoPlanes();
362 /// Gets or sets the buffer flags of the packet.
364 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
365 /// <exception cref="InvalidOperationException">
366 /// The MediaPacket is not in the writable state, which means it is being used by another module.
368 public MediaPacketBufferFlags BufferFlags
372 ValidateNotDisposed();
376 int ret = Interop.MediaPacket.GetBufferFlags(_handle, out value);
378 MultimediaDebug.AssertNoError(ret);
380 return (MediaPacketBufferFlags)value;
385 ValidateNotDisposed();
388 int ret = Interop.MediaPacket.ResetBufferFlags(_handle);
390 MultimediaDebug.AssertNoError(ret);
392 ret = Interop.MediaPacket.SetBufferFlags(_handle, (int)value);
394 MultimediaDebug.AssertNoError(ret);
399 /// Gets a value indicating whether the packet has been disposed of.
401 /// <value>true if the packet has been disposed of; otherwise, false.</value>
402 public bool IsDisposed
410 private bool _isDisposed = false;
414 /// Releases all resources used by the <see cref="MediaPacket"/> object.
416 /// <exception cref="InvalidOperationException">
417 /// The MediaPacket can not be disposed, which means it is being used by another module.
419 public void Dispose()
428 GC.SuppressFinalize(this);
432 /// Releases the resources used by the <see cref="MediaPacket"/> object.
434 /// <param name="disposing">
435 /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
437 protected virtual void Dispose(bool disposing)
444 if (_handle != IntPtr.Zero)
446 Interop.MediaPacket.Destroy(_handle);
447 _handle = IntPtr.Zero;
453 internal IntPtr GetHandle()
455 ValidateNotDisposed();
457 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
463 /// Validates the current object has not been disposed of.
465 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
466 private void ValidateNotDisposed()
470 throw new ObjectDisposedException("This packet has already been disposed of.");
475 /// Ensures whether the packet is writable.
477 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
478 /// <exception cref="InvalidOperationException">The MediaPacket is being used by another module.</exception>
479 internal void EnsureWritableState()
481 ValidateNotDisposed();
486 /// Ensures whether the packet is readable.
488 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
489 internal void EnsureReadableState()
491 ValidateNotDisposed();
495 /// Gets a value indicating whether the packet is in the raw video format.
497 /// <value>true if the packet is in the raw video format; otherwise, false.</value>
498 private bool IsVideoPlaneSupported
502 return !IsEncoded && Format.Type == MediaFormatType.Video;
507 /// Retrieves video planes of the current packet.
509 /// <returns>The <see cref="MediaPacketVideoPlane"/>s allocated to the current MediaPacket.</returns>
510 private MediaPacketVideoPlane[] GetVideoPlanes()
512 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
514 uint numberOfPlanes = 0;
515 int ret = Interop.MediaPacket.GetNumberOfVideoPlanes(_handle, out numberOfPlanes);
517 MultimediaDebug.AssertNoError(ret);
519 MediaPacketVideoPlane[] planes = new MediaPacketVideoPlane[numberOfPlanes];
521 for (int i = 0; i < numberOfPlanes; ++i)
523 planes[i] = new MediaPacketVideoPlane(this, i);
530 /// Retrieves the buffer of the current packet.
532 /// <returns>The <see cref="MediaPacketBuffer"/> allocated to the current MediaPacket.</returns>
533 private MediaPacketBuffer GetBuffer()
535 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
539 int ret = Interop.MediaPacket.GetBufferData(_handle, out dataHandle);
540 MultimediaDebug.AssertNoError(ret);
542 Debug.Assert(dataHandle != IntPtr.Zero, "Data handle is invalid!");
545 ret = Interop.MediaPacket.GetAllocatedBufferSize(_handle, out size);
546 MultimediaDebug.AssertNoError(ret);
548 return new MediaPacketBuffer(this, dataHandle, size);
552 /// Creates an object of the MediaPacket with the specified <see cref="MediaFormat"/>.
554 /// <param name="format">The media format for the new packet.</param>
555 /// <returns>A new MediaPacket object.</returns>
556 public static MediaPacket Create(MediaFormat format)
558 return new SimpleMediaPacket(format);
561 internal static MediaPacket From(IntPtr handle)
563 return new SimpleMediaPacket(handle);
567 internal class SimpleMediaPacket : MediaPacket
569 internal SimpleMediaPacket(MediaFormat format) : base(format)
573 internal SimpleMediaPacket(IntPtr handle) : base(handle)