From: coderhyme Date: Fri, 28 Oct 2016 04:11:09 +0000 (+0900) Subject: Add implementation of MediaCodec X-Git-Tag: submit/trunk/20170823.075128~94^2~188^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7d53cebe448bd0acbcdc84c560f96f3a33f9f015;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git Add implementation of MediaCodec Change-Id: I4eaa26db4e251bc88fd3366ad917f98b23fc2e06 Signed-off-by: coderhyme --- diff --git a/src/Tizen.Multimedia/Interop/Interop.MediaCodec.cs b/src/Tizen.Multimedia/Interop/Interop.MediaCodec.cs index e65bf8b..149079d 100644 --- a/src/Tizen.Multimedia/Interop/Interop.MediaCodec.cs +++ b/src/Tizen.Multimedia/Interop/Interop.MediaCodec.cs @@ -99,8 +99,7 @@ internal static partial class Interop internal static extern int GetSupportedType(IntPtr handle, int codecType, bool isEncoder, out int value); - // TODO the native method name needs to get replaced with new one which will be added - [DllImport(Libraries.MediaCodec, EntryPoint = "mediacodec_foreach_supported_codec")] + [DllImport(Libraries.MediaCodec, EntryPoint = "mediacodec_foreach_supported_codec_static")] internal static extern int ForeachSupportedCodec(SupportedCodecCallback cb, IntPtr arg); } } diff --git a/src/Tizen.Multimedia/MediaCodec/BufferStatusChangedEventArgs.cs b/src/Tizen.Multimedia/MediaCodec/BufferStatusChangedEventArgs.cs new file mode 100644 index 0000000..ebbf589 --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/BufferStatusChangedEventArgs.cs @@ -0,0 +1,49 @@ +/* + * 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; + +namespace Tizen.Multimedia.MediaCodec +{ + /// + /// Provides data for the event. + /// + public class BufferStatusChangedEventArgs : EventArgs + { + private readonly MediaCodecStatus _status; + + /// + /// Initializes a new instance of the BufferStatusChangedEventArgs class. + /// + /// The value representing new status of the codec. + public BufferStatusChangedEventArgs(MediaCodecStatus status) + { + _status = status; + } + + /// + /// Gets the value indicating new status of the codec. + /// + public MediaCodecStatus Status + { + get + { + return _status; + } + } + + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/EosReachedEventArgs.cs b/src/Tizen.Multimedia/MediaCodec/EosReachedEventArgs.cs new file mode 100644 index 0000000..a5d5c0e --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/EosReachedEventArgs.cs @@ -0,0 +1,33 @@ +/* + * 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; + +namespace Tizen.Multimedia.MediaCodec +{ + /// + /// Provides data for the event. + /// + public class EosReachedEventArgs : EventArgs + { + /// + /// Initializes a new instance of the EosReachedEventArgs class. + /// + public EosReachedEventArgs() + { + } + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/ErrorOccurredEventArgs.cs b/src/Tizen.Multimedia/MediaCodec/ErrorOccurredEventArgs.cs new file mode 100644 index 0000000..db54681 --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/ErrorOccurredEventArgs.cs @@ -0,0 +1,48 @@ +/* + * 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; + +namespace Tizen.Multimedia.MediaCodec +{ + /// + /// Provides data for the event. + /// + public class ErrorOccurredEventArgs : EventArgs + { + private readonly MediaCodecError _error; + + /// + /// Initializes a new instance of the ErrorOccurredEventArgs class. + /// + /// The value representing the type of the error. + public ErrorOccurredEventArgs(MediaCodecError error) + { + _error = error; + } + + /// + /// Gets the value indicating what kind of the error. + /// + public MediaCodecError Error + { + get + { + return _error; + } + } + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/InputProcessedEventArgs.cs b/src/Tizen.Multimedia/MediaCodec/InputProcessedEventArgs.cs new file mode 100644 index 0000000..95fffb9 --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/InputProcessedEventArgs.cs @@ -0,0 +1,51 @@ +/* + * 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; + +namespace Tizen.Multimedia.MediaCodec +{ + /// + /// Provides data for the event. + /// + public class InputProcessedEventArgs : EventArgs + { + private readonly MediaPacket _packet; + + /// + /// Initializes a new instance of the InputProcessedEventArgs class. + /// + /// The packet that the codec has processed. + public InputProcessedEventArgs(MediaPacket packet) + { + Debug.Assert(packet != null); + + _packet = packet; + } + + /// + /// Gets the packet that the codec has processed. + /// + public MediaPacket Packet + { + get + { + return _packet; + } + } + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/MediaCodec.cs b/src/Tizen.Multimedia/MediaCodec/MediaCodec.cs new file mode 100644 index 0000000..50db753 --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/MediaCodec.cs @@ -0,0 +1,725 @@ +/* + * 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.Collections.Generic; +using System.Diagnostics; + +namespace Tizen.Multimedia.MediaCodec +{ + /// + /// Provides the means to encode and decode video and audio data. + /// + public class MediaCodec : IDisposable + { + private static readonly int CodecTypeMask = 0xFFFF; + private static readonly int CodecKindMask = 0x3000; + private static readonly int CodecKindAudio = 0x1000; + private static readonly int CodecKindVideo = 0x2000; + + private IntPtr _handle; + + /// + /// Initialize a new instance of the MediaCodec class. + /// + public MediaCodec() + { + int ret = Interop.MediaCodec.Create(out _handle); + + if (ret == (int)MediaCodecErrorCode.InvalidOperation) + { + throw new InvalidOperationException("Not able to initiate a new media codec."); + } + + MediaCodecDebug.AssertNoError(ret); + } + + #region IDisposable-support + private bool _isDisposed = false; + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (_handle != IntPtr.Zero) + { + Interop.MediaCodec.Destroy(_handle); + _handle = IntPtr.Zero; + } + + _isDisposed = true; + } + } + + ~MediaCodec() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + #endregion + + /// + /// Validates if the object already has been disposed of. + /// + /// The current object has been disposed of. + private void ValidateNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(MediaCodec)); + } + } + + private static IEnumerable _supportedVideoCodecs; + + /// + /// Gets the audio codec list that the current device supports. + /// + public static IEnumerable SupportedVideoCodecs + { + get + { + if (_supportedVideoCodecs == null) + { + LoadSupportedCodec(); + } + + return _supportedVideoCodecs; + } + } + + private static IEnumerable _supportedAudioCodecs; + + + /// + /// Gets the audio codec list that the current device supports. + /// + public static IEnumerable SupportedAudioCodecs + { + get + { + if (_supportedAudioCodecs == null) + { + LoadSupportedCodec(); + } + + return _supportedAudioCodecs; + } + } + + private static bool TryGetMimeTypeFromCodecType(int codecType, ref T result) + { + foreach (T value in Enum.GetValues(typeof(T))) + { + if ((Convert.ToInt32(value) & CodecTypeMask) == codecType) + { + result = value; + return true; + } + } + + Debug.Fail($"Unknown codec : { codecType }."); + return false; + } + + private static void LoadSupportedCodec() + { + var videoCodecList = new List(); + var audioCodecList = new List(); + + Interop.MediaCodec.SupportedCodecCallback cb = (int codecType, IntPtr arg) => + { + if ((codecType & CodecKindMask) == CodecKindVideo) + { + MediaFormatVideoMimeType mimeType = 0; + if (TryGetMimeTypeFromCodecType(codecType, ref mimeType)) + { + videoCodecList.Add(mimeType); + } + } + else + { + MediaFormatAudioMimeType mimeType = 0; + if (TryGetMimeTypeFromCodecType(codecType, ref mimeType)) + { + audioCodecList.Add(mimeType); + } + } + + return true; + }; + + int ret = Interop.MediaCodec.ForeachSupportedCodec(cb, IntPtr.Zero); + + MediaCodecDebug.AssertNoError(ret); + + _supportedVideoCodecs = videoCodecList.AsReadOnly(); + _supportedAudioCodecs = audioCodecList.AsReadOnly(); + } + + /// + /// Prepares the MediaCodec for encoding or decoding. + /// + /// + /// The codec is not configured, yet. + /// -or- + /// Internal error. + /// + public void Prepare() + { + ValidateNotDisposed(); + + int ret = Interop.MediaCodec.Prepare(_handle); + + if (ret == (int)MediaCodecErrorCode.NotInitialized) + { + throw new InvalidOperationException("The codec is not configured."); + } + if (ret != (int)MediaCodecErrorCode.None) + { + throw new InvalidOperationException("Operation failed."); + } + + MediaCodecDebug.AssertNoError(ret); + } + + /// + /// Unprepares the MediaCodec. + /// + public void Unprepare() + { + ValidateNotDisposed(); + + int ret = Interop.MediaCodec.Unprepare(_handle); + + MediaCodecDebug.AssertNoError(ret); + } + + /// + /// Configures the MediaCodec. + /// + /// The for properties of media data to decode or encode. + /// The value indicating whether the codec works as a encoder or a decoder. + /// The value indicating whether the codec uses hardware acceleration. + /// format is null + /// + /// codecType is invalid. + /// -or- + /// format is neither audio type or video type. + /// + /// the mime type of the format is not supported. + /// + /// + public void Configure(MediaFormat format, bool encoder, MediaCodecTypes codecType) + { + ValidateNotDisposed(); + + if (format == null) + { + throw new ArgumentNullException("Format can't be null."); + } + + if (codecType != MediaCodecTypes.Hardware && codecType != MediaCodecTypes.Software) + { + throw new ArgumentException("codecType is invalid."); + } + + if (format.Type == MediaFormatType.Audio) + { + ConfigureAudio((AudioMediaFormat)format, encoder, codecType); + } + else if (format.Type == MediaFormatType.Video) + { + ConfigureVideo((VideoMediaFormat)format, encoder, codecType); + } + else + { + throw new ArgumentException("Only video and audio formats are allowed."); + } + } + + private void ConfigureAudio(AudioMediaFormat format, bool encoder, + MediaCodecTypes supportType) + { + int codecType = (int)format.MimeType & CodecTypeMask; + + if (!Enum.IsDefined(typeof(SupportedCodecType), codecType)) + { + throw new NotSupportedException("The format is not supported " + + $"mime type : { Enum.GetName(typeof(MediaFormatAudioMimeType), format.MimeType) }"); + } + + DoConfigure(codecType, encoder, supportType); + + if (encoder) + { + int ret = Interop.MediaCodec.SetAudioEncoderInfo(_handle, format.SampleRate, + format.Channel, format.Bit, format.BitRate); + + MediaCodecDebug.AssertNoError(ret); + } + else + { + int ret = Interop.MediaCodec.SetAudioDecoderInfo(_handle, format.SampleRate, + format.Channel, format.Bit); + + MediaCodecDebug.AssertNoError(ret); + } + } + + private void ConfigureVideo(VideoMediaFormat format, bool encoder, + MediaCodecTypes supportType) + { + int codecType = (int)format.MimeType & CodecTypeMask; + + if (!Enum.IsDefined(typeof(SupportedCodecType), codecType)) + { + throw new NotSupportedException("The format is not supported." + + $"mime type : { Enum.GetName(typeof(MediaFormatVideoMimeType), format.MimeType) }"); + } + + DoConfigure(codecType, encoder, supportType); + + if (encoder) + { + int ret = Interop.MediaCodec.SetVideoEncoderInfo(_handle, format.Width, + format.Height, format.FrameRate, format.BitRate / 1000); + + MediaCodecDebug.AssertNoError(ret); + } + else + { + int ret = Interop.MediaCodec.SetVideoDecoderInfo(_handle, format.Width, format.Height); + + MediaCodecDebug.AssertNoError(ret); + } + } + + private void DoConfigure(int codecType, bool encoder, MediaCodecTypes supportType) + { + Debug.Assert(Enum.IsDefined(typeof(SupportedCodecType), codecType)); + + int flags = (int)(encoder ? MediaCodecCodingType.Encoder : MediaCodecCodingType.Decoder); + + flags |= (int)supportType; + + int ret = Interop.MediaCodec.Configure(_handle, codecType, flags); + + if (ret == (int)MediaCodecErrorCode.NotSupportedOnDevice) + { + throw new NotSupportedException("The format is not supported."); + } + MediaCodecDebug.AssertNoError(ret); + } + + /// + /// Add the packet to the internal queue of the codec. + /// + /// The packet to be encoded or decoded. + /// packet is null. + /// the current codec is not prepared, yet. + /// Any attempts to modify the packet will be failed until the event for the packet is invoked. + public void ProcessInput(MediaPacket packet) + { + ValidateNotDisposed(); + + if (packet == null) + { + throw new ArgumentNullException("Packet can't be null"); + } + + MediaPacket.Lock packetLock = new MediaPacket.Lock(packet); + + int ret = Interop.MediaCodec.Process(_handle, packetLock.GetHandle(), 0); + + if (ret == (int)MediaCodecErrorCode.InvalidState) + { + throw new InvalidOperationException("The codec is in invalid state."); + } + + MediaCodecDebug.AssertNoError(ret); + } + + /// + /// Flush both input and output buffers. + /// + public void FlushBuffers() + { + ValidateNotDisposed(); + + int ret = Interop.MediaCodec.FlushBuffers(_handle); + + MediaCodecDebug.AssertNoError(ret); + } + + /// + /// Retrieves supported codec types for the specified params. + /// + /// The value indicating encoder or decoder. + /// The mime type to query. + /// The values indicating which codec types are supported on the current device. + /// type is invalid. + public MediaCodecTypes GetCodecType(bool encoder, MediaFormatVideoMimeType type) + { + ValidateNotDisposed(); + + if (CheckMimeType(typeof(MediaFormatVideoMimeType), (int)type) == false) + { + return 0; + } + + return GetCodecType((int)type, encoder); + } + + /// + /// Retrieves supported codec types for the specified params. + /// + /// The value indicating encoder or decoder. + /// The mime type to query. + /// The values indicating which codec types are supported on the current device. + /// type is invalid. + public MediaCodecTypes GetCodecType(bool encoder, MediaFormatAudioMimeType type) + { + ValidateNotDisposed(); + + if (CheckMimeType(typeof(MediaFormatAudioMimeType), (int)type) == false) + { + return 0; + } + + return GetCodecType((int)type, encoder); + } + + private MediaCodecTypes GetCodecType(int mimeType, bool isEncoder) + { + int codecType = mimeType & CodecTypeMask; + int value = 0; + + int ret = Interop.MediaCodec.GetSupportedType(_handle, codecType, isEncoder, out value); + + MediaCodecDebug.AssertNoError(ret); + + return (MediaCodecTypes)value; + } + + private bool CheckMimeType(Type type, int value) + { + int codecType = value & CodecTypeMask; + + if (!Enum.IsDefined(type, value)) + { + throw new ArgumentException($"The mime type value is invalid : { value }."); + } + + return Enum.IsDefined(typeof(SupportedCodecType), codecType); + } + + #region OutputAvailable event + private EventHandler _outputAvailable; + private Interop.MediaCodec.OutputBufferAvailableCallback _outputBufferAvailableCb; + + /// + /// Occurs when an output buffer is available. + /// + /// The output packet needs to be disposed after it is used to clean up unmanaged resources. + public event EventHandler OutputAvailable + { + add + { + ValidateNotDisposed(); + + if (_outputAvailable == null) + { + RegisterOutputAvailableCallback(); + } + _outputAvailable += value; + + } + remove + { + ValidateNotDisposed(); + + _outputAvailable -= value; + if (_outputAvailable == null) + { + UnregisterOutputAvailableCallback(); + } + } + } + + private void RegisterOutputAvailableCallback() + { + _outputBufferAvailableCb = (IntPtr packetHandle, IntPtr arg) => + { + OutputAvailableEventArgs args = null; + + try + { + args = new OutputAvailableEventArgs(packetHandle); + } + catch (Exception) + { + Interop.MediaPacket.Destroy(packetHandle); + throw; + } + + _outputAvailable?.Invoke(this, args); + }; + + int ret = Interop.MediaCodec.SetOutputBufferAvaiableCb(_handle, + _outputBufferAvailableCb, IntPtr.Zero); + + MediaCodecDebug.AssertNoError(ret); + } + + private void UnregisterOutputAvailableCallback() + { + int ret = Interop.MediaCodec.UnsetOutputBufferAvaiableCb(_handle); + + MediaCodecDebug.AssertNoError(ret); + } + #endregion + + #region InputProcessed event + private EventHandler _inputProcessed; + private Interop.MediaCodec.InputBufferUsedCallback _inputBufferUsedCb; + + /// + /// Occurs when an input packet is processed. + /// + /// + public event EventHandler InputProcessed + { + add + { + ValidateNotDisposed(); + + if (_inputProcessed == null) + { + RegisterInputProcessed(); + } + _inputProcessed += value; + + } + remove + { + ValidateNotDisposed(); + + _inputProcessed -= value; + if (_inputProcessed == null) + { + UnregisterInputProcessed(); + } + } + } + + private void RegisterInputProcessed() + { + _inputBufferUsedCb = (IntPtr lockedPacketHandle, IntPtr arg) => + { + MediaPacket packet = null; + + // Lock must be disposed here, note that the packet won't be disposed. + using (MediaPacket.Lock packetLock = + MediaPacket.Lock.FromHandle(lockedPacketHandle)) + { + packet = packetLock.MediaPacket; + } + Debug.Assert(packet != null); + + _inputProcessed?.Invoke(this, new InputProcessedEventArgs(packet)); + }; + + int ret = Interop.MediaCodec.SetInputBufferUsedCb(_handle, + _inputBufferUsedCb, IntPtr.Zero); + + MediaCodecDebug.AssertNoError(ret); + } + + private void UnregisterInputProcessed() + { + int ret = Interop.MediaCodec.UnsetInputBufferUsedCb(_handle); + + MediaCodecDebug.AssertNoError(ret); + } + #endregion + + #region ErrorOccurred event + private EventHandler _errorOccurred; + private Interop.MediaCodec.ErrorCallback _errorCb; + + /// + /// Occurs whenever an error is produced in the codec. + /// + public event EventHandler ErrorOccurred + { + add + { + ValidateNotDisposed(); + + if (_errorOccurred == null) + { + RegisterErrorOccurred(); + } + _errorOccurred += value; + + } + remove + { + ValidateNotDisposed(); + + _errorOccurred -= value; + if (_errorOccurred == null) + { + UnregisterErrorOccurred(); + } + } + } + + private void RegisterErrorOccurred() + { + _errorCb = (int errorCode, IntPtr arg) => + { + MediaCodecError error = (Enum.IsDefined(typeof(MediaCodecError), errorCode)) ? + (MediaCodecError)errorCode : MediaCodecError.InternalError; + + _errorOccurred?.Invoke(this, new ErrorOccurredEventArgs(error)); + }; + int ret = Interop.MediaCodec.SetErrorCb(_handle, _errorCb, IntPtr.Zero); + + MediaCodecDebug.AssertNoError(ret); + } + + private void UnregisterErrorOccurred() + { + int ret = Interop.MediaCodec.UnsetErrorCb(_handle); + + MediaCodecDebug.AssertNoError(ret); + } + #endregion + + #region EosReached event + private EventHandler _eosReached; + private Interop.MediaCodec.EosCallback _eosCb; + + /// + /// Occurs when the codec processes all input data. + /// + public event EventHandler EosReached + { + add + { + ValidateNotDisposed(); + + if (_eosReached == null) + { + RegisterEosReached(); + } + _eosReached += value; + + } + remove + { + ValidateNotDisposed(); + + _eosReached -= value; + if (_eosReached == null) + { + UnregisterEosReached(); + } + } + } + + private void RegisterEosReached() + { + _eosCb = (IntPtr arg) => _eosReached?.Invoke(this, new EosReachedEventArgs()); + + int ret = Interop.MediaCodec.SetEosCb(_handle, _eosCb, IntPtr.Zero); + + MediaCodecDebug.AssertNoError(ret); + } + + private void UnregisterEosReached() + { + int ret = Interop.MediaCodec.UnsetEosCb(_handle); + + MediaCodecDebug.AssertNoError(ret); + } + #endregion + + #region BufferStatusChanged event + private EventHandler _bufferStatusChanged; + private Interop.MediaCodec.BufferStatusCallback _bufferStatusCb; + + /// + /// Occurs when the codec needs more data or has enough data. + /// + public event EventHandler BufferStatusChanged + { + add + { + ValidateNotDisposed(); + + if (_bufferStatusChanged == null) + { + RegisterBufferStatusChanged(); + } + _bufferStatusChanged += value; + + } + remove + { + ValidateNotDisposed(); + + _bufferStatusChanged -= value; + if (_bufferStatusChanged == null) + { + UnregisterBufferStatusChanged(); + } + } + } + + private void RegisterBufferStatusChanged() + { + _bufferStatusCb = (int statusCode, IntPtr arg) => + { + Debug.Assert(Enum.IsDefined(typeof(MediaCodecStatus), statusCode), + $"{ statusCode } is not defined in MediaCodecStatus!"); + + _bufferStatusChanged?.Invoke(this, + new BufferStatusChangedEventArgs((MediaCodecStatus)statusCode)); + }; + + int ret = Interop.MediaCodec.SetBufferStatusCb(_handle, _bufferStatusCb, IntPtr.Zero); + + MediaCodecDebug.AssertNoError(ret); + } + + private void UnregisterBufferStatusChanged() + { + int ret = Interop.MediaCodec.UnsetBufferStatusCb(_handle); + + MediaCodecDebug.AssertNoError(ret); + } + #endregion + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/MediaCodecDebug.cs b/src/Tizen.Multimedia/MediaCodec/MediaCodecDebug.cs new file mode 100644 index 0000000..75d409c --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/MediaCodecDebug.cs @@ -0,0 +1,32 @@ +/* + * 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.Diagnostics; + +namespace Tizen.Multimedia.MediaCodec +{ + internal class MediaCodecDebug + { + + [ConditionalAttribute("DEBUG")] + internal static void AssertNoError(int errorCode) + { + Debug.Assert(errorCode == (int)MediaCodecErrorCode.None, + $"The API is supposed not to return an error! But it returns error({ errorCode}).", + "Implementation of core may have been changed, modify the call to throw if the return code is not ok."); + } + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/MediaCodecError.cs b/src/Tizen.Multimedia/MediaCodec/MediaCodecError.cs new file mode 100644 index 0000000..14508f2 --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/MediaCodecError.cs @@ -0,0 +1,54 @@ +/* + * 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 Tizen.Internals.Errors; + +namespace Tizen.Multimedia.MediaCodec +{ + internal enum MediaCodecErrorCode + { + CodecDefinedBase = -0x019B0000, + + None = ErrorCode.None, + OutOfMemory = ErrorCode.OutOfMemory, + InvalidParameter = ErrorCode.InvalidParameter, + InvalidOperation = ErrorCode.InvalidParameter, + NotSupportedOnDevice = ErrorCode.NotSupported, + PermissionDenied = ErrorCode.PermissionDenied, + + InvalidState = CodecDefinedBase | 0x01, + InvalidInBuffer = CodecDefinedBase | 0x02, + InvalidOutBuffer = CodecDefinedBase | 0x03, + Internal = CodecDefinedBase | 0x04, + NotInitialized = CodecDefinedBase | 0x05, + InvalidStream = CodecDefinedBase | 0x06, + CodecNotFound = CodecDefinedBase | 0x07, + DecodingError = CodecDefinedBase | 0x08, + OutOfStorage = CodecDefinedBase | 0x09, + StreamNotFound = CodecDefinedBase | 0x0a, + NotSupportedFormat = CodecDefinedBase | 0x0b, + NoAvailableBuffer = CodecDefinedBase | 0x0c, + OverflowInBuffer = CodecDefinedBase | 0x0d, + } + + public enum MediaCodecError + { + NotSupportedFormat = MediaCodecErrorCode.NotSupportedFormat, + InternalError = MediaCodecErrorCode.Internal, + OutOfStorage = MediaCodecErrorCode.OutOfStorage, + InvalidStream = MediaCodecErrorCode.InvalidStream, + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/MediaCodecStatus.cs b/src/Tizen.Multimedia/MediaCodec/MediaCodecStatus.cs new file mode 100644 index 0000000..32e453d --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/MediaCodecStatus.cs @@ -0,0 +1,34 @@ +/* + * 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. + */ + +namespace Tizen.Multimedia.MediaCodec +{ + /// + /// Specifies the status of a codec. + /// + public enum MediaCodecStatus + { + /// + /// Not enough data to decode or encode. + /// + LackOfData, + + /// + /// Enough data to decode or encode. + /// + EnoughData + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/MediaCodecType.cs b/src/Tizen.Multimedia/MediaCodec/MediaCodecType.cs new file mode 100644 index 0000000..34da665 --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/MediaCodecType.cs @@ -0,0 +1,44 @@ +/* + * 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; + +namespace Tizen.Multimedia.MediaCodec +{ + [Flags] + internal enum MediaCodecCodingType + { + Encoder = 0x1, + Decoder = 0x2 + } + + /// + /// Specifies types of codec. + /// + [Flags] + public enum MediaCodecTypes + { + /// + /// The hardware-accelerated codec. + /// + Hardware = 0x4, + + /// + /// The software codec. + /// + Software = 0x8 + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/OutputAvailableEventArgs.cs b/src/Tizen.Multimedia/MediaCodec/OutputAvailableEventArgs.cs new file mode 100644 index 0000000..2afd587 --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/OutputAvailableEventArgs.cs @@ -0,0 +1,45 @@ +/* + * 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; + +namespace Tizen.Multimedia.MediaCodec +{ + /// + /// Provides data for the event. + /// + /// The output packet needs to be disposed after it is used to clean up unmanaged resources. + public class OutputAvailableEventArgs : EventArgs + { + private readonly MediaPacket _packet; + + internal OutputAvailableEventArgs(IntPtr packetHandle) + { + _packet = MediaPacket.From(packetHandle); + } + + /// + /// Gets the result packet. + /// + public MediaPacket Packet + { + get + { + return _packet; + } + } + } +} diff --git a/src/Tizen.Multimedia/MediaCodec/SupportedCodecType.cs b/src/Tizen.Multimedia/MediaCodec/SupportedCodecType.cs new file mode 100644 index 0000000..999808f --- /dev/null +++ b/src/Tizen.Multimedia/MediaCodec/SupportedCodecType.cs @@ -0,0 +1,52 @@ +/* + * 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. + */ + +namespace Tizen.Multimedia.MediaCodec +{ + internal enum SupportedCodecType + { + // L16 = 0x1010, + // ALaw = 0x1020, + // ULaw = 0x1030, + Amr = 0x1040, + AmrNB = 0x1040, + AmrWb = 0x1041, + // G729 = 0x1050, + Aac = 0x1060, + AacLC = 0x1060, + AacHE = 0x1061, + AacHEPS = 0x1062, + MP3 = 0x1070, + Vorbis = 0x1080, + Flac = 0x1090, + Wma1 = 0x10A0, + Wma2 = 0x10A1, + WmaPro = 0x10A2, + WmaLossless = 0x10A3, + + H261 = 0x2010, + H263 = 0x2020, + H264 = 0x2030, + MJpeg = 0x2040, + Mpeg1 = 0x2050, + Mpeg2 = 0x2060, + Mpeg4 = 0x2070, + // Hevc = 0x2080, + // VP8 = 0x2090, + // VP9 = 0x20A0, + // VC1 = 0x20B0, + } +} diff --git a/src/Tizen.Multimedia/Tizen.Multimedia.Net45.csproj b/src/Tizen.Multimedia/Tizen.Multimedia.Net45.csproj index bd71381..2745d8c 100755 --- a/src/Tizen.Multimedia/Tizen.Multimedia.Net45.csproj +++ b/src/Tizen.Multimedia/Tizen.Multimedia.Net45.csproj @@ -57,6 +57,17 @@ + + + + + + + + + + + diff --git a/src/Tizen.Multimedia/Tizen.Multimedia.csproj b/src/Tizen.Multimedia/Tizen.Multimedia.csproj index a46db69..d8fb310 100755 --- a/src/Tizen.Multimedia/Tizen.Multimedia.csproj +++ b/src/Tizen.Multimedia/Tizen.Multimedia.csproj @@ -1,180 +1,191 @@ - - - - Debug - AnyCPU - {0CE698B0-4849-4096-9D7F-30E611F50DAD} - Library - Properties - Tizen.Multimedia - Tizen.Multimedia - 512 - - - .NETStandard - v1.3 - .NETStandard,Version=v1.3 - false - true - $(NoWarn);1701;1702 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - - - Tizen.Multimedia.snk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Debug + AnyCPU + {0CE698B0-4849-4096-9D7F-30E611F50DAD} + Library + Properties + Tizen.Multimedia + Tizen.Multimedia + 512 + + + .NETStandard + v1.3 + .NETStandard,Version=v1.3 + false + true + $(NoWarn);1701;1702 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + + + Tizen.Multimedia.snk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + --> + + --> - <_TargetFrameworkDirectories>$(MSBuildThisFileDirectory) - <_FullFrameworkReferenceAssemblyPaths>$(MSBuildThisFileDirectory) - true - + --> + <_TargetFrameworkDirectories>$(MSBuildThisFileDirectory) + <_FullFrameworkReferenceAssemblyPaths>$(MSBuildThisFileDirectory) + true + \ No newline at end of file