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)
146 case ErrorCode.OutOfMemory:
147 throw new OutOfMemoryException("Failed to allocate buffer for the packet.");
150 throw new InvalidOperationException("Failed to create a packet.");
155 private readonly MediaFormat _format;
158 /// Gets the media format of the current packet.
160 public MediaFormat Format
164 ValidateNotDisposed();
170 /// Gets or sets the PTS(Presentation Time Stamp) value of the current packet.
172 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
173 /// <exception cref="InvalidOperationException">
174 /// The MediaPacket is not in the writable state, which means it is being used by another module.
180 ValidateNotDisposed();
183 int ret = Interop.MediaPacket.GetPts(_handle, out value);
185 MultimediaDebug.AssertNoError(ret);
191 ValidateNotDisposed();
194 int ret = Interop.MediaPacket.SetPts(_handle, value);
196 MultimediaDebug.AssertNoError(ret);
201 /// Gets or sets the DTS(Decoding Time Stamp) value of the current packet.
203 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
204 /// <exception cref="InvalidOperationException">
205 /// The MediaPacket is not in the writable state, which means it is being used by another module.
211 ValidateNotDisposed();
214 int ret = Interop.MediaPacket.GetDts(_handle, out value);
216 MultimediaDebug.AssertNoError(ret);
222 ValidateNotDisposed();
225 int ret = Interop.MediaPacket.SetDts(_handle, value);
227 MultimediaDebug.AssertNoError(ret);
232 /// Gets a value indicating whether the packet is the encoded type.
234 /// <value>true if the packet is the encoded type; otherwise, false.</value>
235 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
236 public bool IsEncoded
240 ValidateNotDisposed();
243 int ret = Interop.MediaPacket.IsEncoded(_handle, out value);
245 MultimediaDebug.AssertNoError(ret);
251 private MediaPacketBuffer _buffer;
254 /// Gets the buffer of the packet.
256 /// <value>The <see cref="MediaPacketBuffer"/> allocated to the packet.
257 /// This property will return null if the packet is in the raw video format.</value>
258 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
259 /// <seealso cref="IsEncoded"/>
260 /// <seealso cref="VideoPlanes"/>
261 public MediaPacketBuffer Buffer
265 ValidateNotDisposed();
267 if (IsVideoPlaneSupported)
274 _buffer = GetBuffer();
282 /// Gets or sets a length of data written in the <see cref="Buffer"/>.
284 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
285 /// <exception cref="ArgumentOutOfRangeException">
286 /// The value specified for this property is less than zero or greater than <see cref="MediaPacketBuffer.Length"/>.</exception>
287 /// <exception cref="InvalidOperationException">
288 /// The MediaPacket has <see cref="VideoPlanes"/> instead of <see cref="Buffer"/>.\n
290 /// The MediaPacket is not in the writable state, which means it is being used by another module.
292 public int BufferWrittenLength
296 ValidateNotDisposed();
299 int ret = Interop.MediaPacket.GetBufferSize(_handle, out value);
300 MultimediaDebug.AssertNoError(ret);
302 Debug.Assert(value < int.MaxValue);
308 ValidateNotDisposed();
311 if (IsVideoPlaneSupported)
313 throw new InvalidOperationException(
314 "This packet uses VideoPlanes instead of Buffer.");
317 Debug.Assert(Buffer != null);
319 if (value < 0 || value >= Buffer.Length)
321 throw new ArgumentOutOfRangeException("value must be less than Buffer.Size.");
324 int ret = Interop.MediaPacket.SetBufferSize(_handle, (ulong)value);
325 MultimediaDebug.AssertNoError(ret);
329 private MediaPacketVideoPlane[] _videoPlanes;
332 /// Gets the video planes of the packet.
334 /// <value>The <see cref="MediaPacketVideoPlane"/>s allocated to the packet.
335 /// This property will return null if the packet is not in the raw video format.</value>
336 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
337 /// <seealso cref="IsEncoded"/>
338 /// <seealso cref="Buffer"/>
339 public MediaPacketVideoPlane[] VideoPlanes
343 ValidateNotDisposed();
345 if (!IsVideoPlaneSupported)
350 if (_videoPlanes == null)
352 _videoPlanes = GetVideoPlanes();
360 /// Gets or sets the buffer flags of the packet.
362 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
363 /// <exception cref="InvalidOperationException">
364 /// The MediaPacket is not in the writable state, which means it is being used by another module.
366 public MediaPacketBufferFlags BufferFlags
370 ValidateNotDisposed();
374 int ret = Interop.MediaPacket.GetBufferFlags(_handle, out value);
376 MultimediaDebug.AssertNoError(ret);
378 return (MediaPacketBufferFlags)value;
383 ValidateNotDisposed();
386 int ret = Interop.MediaPacket.ResetBufferFlags(_handle);
388 MultimediaDebug.AssertNoError(ret);
390 ret = Interop.MediaPacket.SetBufferFlags(_handle, (int)value);
392 MultimediaDebug.AssertNoError(ret);
397 /// Gets a value indicating whether the packet has been disposed of.
399 /// <value>true if the packet has been disposed of; otherwise, false.</value>
400 public bool IsDisposed
408 private bool _isDisposed = false;
412 /// Releases all resources used by the <see cref="MediaPacket"/> object.
414 /// <exception cref="InvalidOperationException">
415 /// The MediaPacket can not be disposed, which means it is being used by another module.
417 public void Dispose()
426 GC.SuppressFinalize(this);
430 /// Releases the resources used by the <see cref="MediaPacket"/> object.
432 /// <param name="disposing">
433 /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
435 protected virtual void Dispose(bool disposing)
442 if (_handle != IntPtr.Zero)
444 Interop.MediaPacket.Destroy(_handle);
445 _handle = IntPtr.Zero;
451 internal IntPtr GetHandle()
453 ValidateNotDisposed();
455 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
461 /// Validates the current object has not been disposed of.
463 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
464 private void ValidateNotDisposed()
468 throw new ObjectDisposedException("This packet has already been disposed of.");
473 /// Ensures whether the packet is writable.
475 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
476 /// <exception cref="InvalidOperationException">The MediaPacket is being used by another module.</exception>
477 internal void EnsureWritableState()
479 ValidateNotDisposed();
484 /// Ensures whether the packet is readable.
486 /// <exception cref="ObjectDisposedException">The MediaPacket has already been disposed of.</exception>
487 internal void EnsureReadableState()
489 ValidateNotDisposed();
493 /// Gets a value indicating whether the packet is in the raw video format.
495 /// <value>true if the packet is in the raw video format; otherwise, false.</value>
496 private bool IsVideoPlaneSupported
500 return !IsEncoded && Format.Type == MediaFormatType.Video;
505 /// Retrieves video planes of the current packet.
507 /// <returns>The <see cref="MediaPacketVideoPlane"/>s allocated to the current MediaPacket.</returns>
508 private MediaPacketVideoPlane[] GetVideoPlanes()
510 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
512 uint numberOfPlanes = 0;
513 int ret = Interop.MediaPacket.GetNumberOfVideoPlanes(_handle, out numberOfPlanes);
515 MultimediaDebug.AssertNoError(ret);
517 MediaPacketVideoPlane[] planes = new MediaPacketVideoPlane[numberOfPlanes];
519 for (int i = 0; i < numberOfPlanes; ++i)
521 planes[i] = new MediaPacketVideoPlane(this, i);
528 /// Retrieves the buffer of the current packet.
530 /// <returns>The <see cref="MediaPacketBuffer"/> allocated to the current MediaPacket.</returns>
531 private MediaPacketBuffer GetBuffer()
533 Debug.Assert(_handle != IntPtr.Zero, "The handle is invalid!");
537 int ret = Interop.MediaPacket.GetBufferData(_handle, out dataHandle);
538 MultimediaDebug.AssertNoError(ret);
540 Debug.Assert(dataHandle != IntPtr.Zero, "Data handle is invalid!");
543 ret = Interop.MediaPacket.GetAllocatedBufferSize(_handle, out size);
544 MultimediaDebug.AssertNoError(ret);
546 return new MediaPacketBuffer(this, dataHandle, size);
550 /// Creates an object of the MediaPacket with the specified <see cref="MediaFormat"/>.
552 /// <param name="format">The media format for the new packet.</param>
553 /// <returns>A new MediaPacket object.</returns>
554 public static MediaPacket Create(MediaFormat format)
556 return new SimpleMediaPacket(format);
559 internal static MediaPacket From(IntPtr handle)
561 return new SimpleMediaPacket(handle);
565 internal class SimpleMediaPacket : MediaPacket
567 internal SimpleMediaPacket(MediaFormat format) : base(format)
571 internal SimpleMediaPacket(IntPtr handle) : base(handle)