/*
* 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
{
///
/// Provides functionality to read a media buffer.
///
public interface IReadOnlyBuffer
{
///
/// Gets or sets a value at the specified index.
///
/// The index of the value to get or set.
///
/// index is less than zero.\n
/// -or-\n
/// index is equal to or greater than .
///
/// The object that owns the current buffer already has been disposed of.
/// The buffer is not available. i.e. not writable state.
byte this[int index]
{
get;
set;
}
///
/// Gets the size of the buffer, in bytes.
///
int Length
{
get;
}
///
/// Copies data from a byte array to the buffer.
///
/// The array to copy to.
/// The zero-based index in the source array where copying should start.
/// The number of array elements to copy.
/// startIndex or length is not valid.
/// The object that owns the current buffer already has been disposed of.
void CopyTo(byte[] dest, int startIndex, int length);
///
/// Copies data from a byte array to the buffer.
///
/// The array to copy to.
/// The zero-based index in the source array where copying should start.
/// The number of array elements to copy.
/// The zero-based index in the buffer where copying should start.
/// startIndex, offset or length is not valid.
/// The object that owns the current buffer already has been disposed of.
void CopyTo(byte[] dest, int startIndex, int length, int offset);
}
///
/// Provides functionality to read and write a media buffer.
///
public interface IMediaBuffer : IReadOnlyBuffer
{
///
/// Copies data from the buffer to a byte array.
///
/// The array to copy from.
/// The zero-based index in the dest array where copying should start.
/// The number of elements to copy.
/// startIndex or length is not valid.
/// The object that owns the current buffer already has been disposed of.
/// The buffer is not available. i.e. not writable state.
void CopyFrom(byte[] source, int startIndex, int length);
///
/// Copies data from the buffer to a byte array.
///
/// The array to copy from.
/// The zero-based index in the dest array where copying should start.
/// The number of elements to copy.
/// The zero-based index in the buffer where copying should start.
/// startIndex, offset or length is not valid.
/// The object that owns the current buffer already has been disposed of.
/// The buffer is not available. i.e. not writable state.
void CopyFrom(byte[] source, int startIndex, int length, int offset);
}
///
/// Represents a buffer for a .
///
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);
}
}
///
/// Validates the range
///
///
///
///
/// offset + length is greater than .\n
/// -or-\n
/// offset or length is less than zero.
///
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; }
}
}