From b23692de2348c74314c04d212d8250b23c5ab058 Mon Sep 17 00:00:00 2001 From: Dinesh Dwivedi Date: Wed, 22 Feb 2017 16:02:55 +0530 Subject: [PATCH] [MM-VideoUtil] Added base code for Video utility Change-Id: Ib1a7f7298b79a85536d4cd4ac513cdde4bad2292 Signed-off-by: Dinesh Dwivedi --- src/Tizen.Multimedia/Interop/Interop.ErrorCode.cs | 9 + src/Tizen.Multimedia/Interop/Interop.Libraries.cs | 1 + src/Tizen.Multimedia/Interop/Interop.VideoUtil.cs | 192 ++++++++++++ src/Tizen.Multimedia/Utility/AudioCodec.cs | 37 +++ src/Tizen.Multimedia/Utility/VideoCodec.cs | 41 +++ src/Tizen.Multimedia/Utility/VideoFileFormat.cs | 33 ++ src/Tizen.Multimedia/Utility/VideoTranscoder.cs | 355 ++++++++++++++++++++++ 7 files changed, 668 insertions(+) create mode 100755 src/Tizen.Multimedia/Interop/Interop.VideoUtil.cs create mode 100755 src/Tizen.Multimedia/Utility/AudioCodec.cs create mode 100755 src/Tizen.Multimedia/Utility/VideoCodec.cs create mode 100755 src/Tizen.Multimedia/Utility/VideoFileFormat.cs create mode 100755 src/Tizen.Multimedia/Utility/VideoTranscoder.cs diff --git a/src/Tizen.Multimedia/Interop/Interop.ErrorCode.cs b/src/Tizen.Multimedia/Interop/Interop.ErrorCode.cs index ec477d6..b941043 100755 --- a/src/Tizen.Multimedia/Interop/Interop.ErrorCode.cs +++ b/src/Tizen.Multimedia/Interop/Interop.ErrorCode.cs @@ -15,6 +15,7 @@ */ using System; +using System.IO; using System.Runtime.CompilerServices; using Tizen; @@ -28,10 +29,16 @@ internal static partial class Interop InvalidOperation = Tizen.Internals.Errors.ErrorCode.InvalidOperation, PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied, NotSupported = Tizen.Internals.Errors.ErrorCode.NotSupported, + ResourceBusy = Tizen.Internals.Errors.ErrorCode.ResourceBusy, + NoSuchFile = Tizen.Internals.Errors.ErrorCode.NoSuchFile, + // Radio InvalidState = -0x019A0000 | 0x01, // RADIO_ERROR_INVALID_STATE SoundPolicy = -0x019A0000 | 0x02, // RADIO_ERROR_SOUND_POLICY NoAntenna = -0x019A0000 | 0x03, // RADIO_ERROR_NO_ANTENNA + + // Image/ Video Utility + NotSupportedFormat = -0x01980000 | 0x01, // VIDEO_UTIL_ERROR_NOT_SUPPORTED_FORMAT } } @@ -85,12 +92,14 @@ internal static class ErrorCodeExtensions //case ErrorCode.None: case Interop.ErrorCode.PermissionDenied: return new UnauthorizedAccessException(errMessage); case Interop.ErrorCode.InvalidParameter: return new ArgumentException(errMessage); + case Interop.ErrorCode.NoSuchFile: return new FileNotFoundException(errMessage); case Interop.ErrorCode.OutOfMemory: return new OutOfMemoryException(errMessage); case Interop.ErrorCode.NotSupported: return new NotSupportedException(errMessage); case Interop.ErrorCode.NoAntenna: return new NotSupportedException(errMessage); case Interop.ErrorCode.InvalidOperation: case Interop.ErrorCode.InvalidState: case Interop.ErrorCode.SoundPolicy: + case Interop.ErrorCode.ResourceBusy: default: return new InvalidOperationException(errMessage); } } diff --git a/src/Tizen.Multimedia/Interop/Interop.Libraries.cs b/src/Tizen.Multimedia/Interop/Interop.Libraries.cs index 54a147b..a78e4d7 100755 --- a/src/Tizen.Multimedia/Interop/Interop.Libraries.cs +++ b/src/Tizen.Multimedia/Interop/Interop.Libraries.cs @@ -32,6 +32,7 @@ internal static partial class Interop public const string Camera = "libcapi-media-camera.so.0"; public const string StreamRecorder = "libcapi-media-streamrecorder.so.0"; public const string Radio = "libcapi-media-radio.so.0"; + public const string VideoUtil = "libcapi-media-video-util.so.0"; public const string ThumbnailExtractor = "libcapi-media-thumbnail-util.so"; public const string WavPlayer = "libcapi-media-wav-player.so.0"; public const string TonePlayer = "libcapi-media-tone-player.so.0"; diff --git a/src/Tizen.Multimedia/Interop/Interop.VideoUtil.cs b/src/Tizen.Multimedia/Interop/Interop.VideoUtil.cs new file mode 100755 index 0000000..f62e6f4 --- /dev/null +++ b/src/Tizen.Multimedia/Interop/Interop.VideoUtil.cs @@ -0,0 +1,192 @@ +/* + * 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal enum VideoCodec + { + Mpeg4, // VIDEO_UTIL_VIDEO_CODEC_MPEG4 + H263, // VIDEO_UTIL_VIDEO_CODEC_H263 + H264, // VIDEO_UTIL_VIDEO_CODEC_H264 + None, // VIDEO_UTIL_VIDEO_CODEC_NONE + } + + internal enum AudioCodec + { + Aac, // VIDEO_UTIL_AUDIO_CODEC_AAC + Amrnb, // VIDEO_UTIL_AUDIO_CODEC_AMRNB + None, // VIDEO_UTIL_AUDIO_CODEC_NONE + } + + internal enum VideoFileFormat + { + Format3Gp, // VIDEO_UTIL_FILE_FORMAT_3GP + FormatMp4, // VIDEO_UTIL_FILE_FORMAT_MP4 + FormatMax, // VIDEO_UTIL_FILE_FORMAT_MAX + } + + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_foreach_supported_file_format")] + internal static extern ErrorCode ForeachSupportedFileFormat(this VideoTranscoderHandle /* video_util_h */ handle, VideoTranscoderHandle.SupportedFileFormatCallback callback, IntPtr /* void */ userData); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_foreach_supported_video_codec")] + internal static extern ErrorCode ForeachSupportedVideoCodec(this VideoTranscoderHandle /* video_util_h */ handle, VideoTranscoderHandle.SupportedVideoEncoderCallback callback, IntPtr /* void */ userData); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_foreach_supported_audio_codec")] + internal static extern ErrorCode ForeachSupportedAudioCodec(this VideoTranscoderHandle /* video_util_h */ handle, VideoTranscoderHandle.SupportedAudioEncoderCallback callback, IntPtr /* void */ userData); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_start_transcoding")] + internal static extern ErrorCode StartTranscoding(this VideoTranscoderHandle /* video_util_h */ handle, ulong start, ulong duration, + string outPath, VideoTranscoderHandle.TranscodingProgressCallback progressCb, VideoTranscoderHandle.TranscodingCompletedCallback completedCb, IntPtr /* void */ userData); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_cancel_transcoding")] + internal static extern ErrorCode CancelTranscoding(this VideoTranscoderHandle /* video_util_h */ handle); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_get_progress_transcoding")] + internal static extern ErrorCode GetProgressTranscoding(this VideoTranscoderHandle /* video_util_h */ handle, out ulong currentPosition, out ulong duration); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_set_resolution")] + internal static extern ErrorCode SetResolution(this VideoTranscoderHandle /* video_util_h */ handle, int width, int height); + + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_set_file_path")] + internal static extern ErrorCode SetFilePath(this VideoTranscoderHandle /* video_util_h */ handle, string path); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_set_accurate_mode")] + internal static extern ErrorCode SetAccurateMode(this VideoTranscoderHandle /* video_util_h */ handle, bool mode); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_set_video_codec")] + internal static extern ErrorCode SetVideoCodec(this VideoTranscoderHandle /* video_util_h */ handle, VideoCodec /* video_util_video_codec_e */ codec); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_set_audio_codec")] + internal static extern ErrorCode SetAudioCodec(this VideoTranscoderHandle /* video_util_h */ handle, AudioCodec /* video_util_audio_codec_e */ codec); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_set_file_format")] + internal static extern ErrorCode SetFileFormat(this VideoTranscoderHandle /* video_util_h */ handle, VideoFileFormat /* video_util_file_format_e */ format); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_set_fps")] + internal static extern ErrorCode SetFps(this VideoTranscoderHandle /* video_util_h */ handle, int fps); + + internal class VideoTranscoderHandle : SafeMultimediaHandle + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void TranscodingProgressCallback(ulong currentPosition, ulong duration, IntPtr /* void */ userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void TranscodingCompletedCallback(ErrorCode /* video_util_error_e */ errorCode, IntPtr /* void */ userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool SupportedFileFormatCallback(VideoFileFormat /* video_util_file_format_e */ format, IntPtr /* void */ userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool SupportedVideoEncoderCallback(VideoCodec /* video_util_video_codec_e */ codec, IntPtr /* void */ userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool SupportedAudioEncoderCallback(AudioCodec /* video_util_audio_codec_e */ codec, IntPtr /* void */ userData); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_create")] + internal static extern ErrorCode Create(out IntPtr /* video_util_h */ handle); + + [DllImport(Libraries.VideoUtil, EntryPoint = "video_util_destroy")] + internal static extern ErrorCode Destroy(IntPtr /* video_util_h */ handle); + + internal string InputFile + { + set { NativeSet(this.SetFilePath, value); } + } + + internal bool AccurateModeEnabled + { + set { NativeSet(this.SetAccurateMode, value); } + } + + internal VideoCodec VideoCodec + { + set { NativeSet(this.SetVideoCodec, value); } + } + + internal AudioCodec AudioCodec + { + set { NativeSet(this.SetAudioCodec, value); } + } + + internal VideoFileFormat FileFormat + { + set { NativeSet(this.SetFileFormat, value); } + } + + internal int Fps + { + set { NativeSet(this.SetFps, value); } + } + + internal VideoTranscoderHandle(IntPtr handle, bool needToRelease) : base(handle, needToRelease) + { + } + + internal VideoTranscoderHandle() : this(CreateNativeHandle(), true) + { + } + + internal static IntPtr CreateNativeHandle() + { + IntPtr handle; + Create(out handle).ThrowIfFailed("Failed to create native handle"); + return handle; + } + + internal override ErrorCode DisposeNativeHandle() + { + return Destroy(handle); + } + + internal void ForeachSupportedFileFormat(Action action) + { + SupportedFileFormatCallback callback = (codec, userData) => + { + action(codec); + return true; + }; + + this.ForeachSupportedFileFormat(callback, IntPtr.Zero).ThrowIfFailed("Failed to get supported file format list from native handle"); + } + + internal void ForeachSupportedVideoCodec(Action action) + { + SupportedVideoEncoderCallback callback = (codec, userData) => + { + action(codec); + return true; + }; + + this.ForeachSupportedVideoCodec(callback, IntPtr.Zero).ThrowIfFailed("Failed to get supported video codec list from native handle"); + } + + internal void ForeachSupportedAudioCodec(Action action) + { + SupportedAudioEncoderCallback callback = (codec, userData) => + { + action(codec); + return true; + }; + + this.ForeachSupportedAudioCodec(callback, IntPtr.Zero).ThrowIfFailed("Failed to get supported audio codec list from native handle"); + } + } +} diff --git a/src/Tizen.Multimedia/Utility/AudioCodec.cs b/src/Tizen.Multimedia/Utility/AudioCodec.cs new file mode 100755 index 0000000..47cb060 --- /dev/null +++ b/src/Tizen.Multimedia/Utility/AudioCodec.cs @@ -0,0 +1,37 @@ +/* + * 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.Utility +{ + /// + /// Audio codec + /// + public enum AudioCodec + { + /// + /// No trans-coding for audio + /// + None = Interop.AudioCodec.None, + /// + /// AAC + /// + Aac = Interop.AudioCodec.Aac, + /// + /// AMRNB + /// + Amrnb = Interop.AudioCodec.Amrnb, + } +} \ No newline at end of file diff --git a/src/Tizen.Multimedia/Utility/VideoCodec.cs b/src/Tizen.Multimedia/Utility/VideoCodec.cs new file mode 100755 index 0000000..718507d --- /dev/null +++ b/src/Tizen.Multimedia/Utility/VideoCodec.cs @@ -0,0 +1,41 @@ +/* + * 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.Utility +{ + /// + /// Video codec for trans-coding + /// + public enum VideoCodec + { + /// + /// No trans-coding for video + /// + None = Interop.VideoCodec.None, + /// + /// MPEG4 + /// + Mpeg4 = Interop.VideoCodec.Mpeg4, + /// + /// H263 + /// + H263 = Interop.VideoCodec.H263, + /// + /// H264 + /// + H264 = Interop.VideoCodec.H264, + } +} \ No newline at end of file diff --git a/src/Tizen.Multimedia/Utility/VideoFileFormat.cs b/src/Tizen.Multimedia/Utility/VideoFileFormat.cs new file mode 100755 index 0000000..5afe29a --- /dev/null +++ b/src/Tizen.Multimedia/Utility/VideoFileFormat.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. + */ + +namespace Tizen.Multimedia.Utility +{ + /// + /// Video file format + /// + public enum VideoFileFormat + { + /// + /// 3GP file + /// + ThreeGp = Interop.VideoFileFormat.Format3Gp, + /// + /// MP4 file + /// + Mp4 = Interop.VideoFileFormat.FormatMp4, + } +} \ No newline at end of file diff --git a/src/Tizen.Multimedia/Utility/VideoTranscoder.cs b/src/Tizen.Multimedia/Utility/VideoTranscoder.cs new file mode 100755 index 0000000..719bd8a --- /dev/null +++ b/src/Tizen.Multimedia/Utility/VideoTranscoder.cs @@ -0,0 +1,355 @@ +/* + * 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.Threading; +using System.Threading.Tasks; + +namespace Tizen.Multimedia.Utility +{ + /// + /// Video trans-coding utility + /// + public class VideoTranscoder : IDisposable + { + public const AudioCodec DetaultAudioCodec = AudioCodec.Aac; + public const VideoCodec DetaultVideoCodec = VideoCodec.Mpeg4; + public const VideoFileFormat DetaultFileFormat = VideoFileFormat.ThreeGp; + public const bool DefaultAccurateModeEnabled = false; + public static Size DefaultResolution = new Size(0, 0); + public const int DefaultFps = 0; + + internal Interop.VideoTranscoderHandle _handle; + private Size _resolution = DefaultResolution; + private int _fps = DefaultFps; + + /// + /// Creates Video trans-coder + /// + /// Thrown if framework failed to allocate memory + /// Thrown if video trans-coding is not supported in device + public VideoTranscoder() + { + _handle = new Interop.VideoTranscoderHandle(); + } + + /// + /// Indicate if trans-coder is busy trans-coding + /// + public bool IsBusy { get; private set; } + + /// + /// Indicates if accurate mode is enabled + /// + /// Default is false, if set to true, next trans-coding will start from accurate frame for given the duration, otherwise from nearest i-frame + public bool IsAccurateModeEnabled { get; set; } = DefaultAccurateModeEnabled; + + /// + /// Audio codec for encoding stream for next trans-coding + /// + /// Default is AudioCodec.Aac + public AudioCodec AudioCodec { get; set; } = DetaultAudioCodec; + + /// + /// Video codec for encoding stream for next trans-coding + /// + /// Default is VideoCodec.Mpeg4 + public VideoCodec VideoCodec { get; set; } = DetaultVideoCodec; + + /// + /// File format for trans-coding media stream for next trans-coding + /// + /// Default is VideoFileFormat.ThreeGp + public VideoFileFormat Format { get; set; } = DetaultFileFormat; + + /// + /// Media resolution for next trans-coding + /// + /// + /// Default value is Size(0, 0) + /// If the width is 0, it set original size.(minimum value is 128) + /// If the height is 0, it set original size.(minimum value is 96) + /// + /// Thrown if value is not in valid range + public Size Resolution + { + get { return _resolution; } + set + { + ValidateInputRange(value.Width, () => value.Width >= 128 || value.Width == 0, "Width", "Valid value is 0 and value >= 128"); + ValidateInputRange(value.Height, () => value.Width >= 96 || value.Width == 0, "Height", "Valid value is 0 and value >= 96"); + _resolution = value; + } + } + + /// + /// Frame rate, in range [5-30] for next trans-coding + /// + /// + /// Default value is 0 + /// If fps is set 0, the default is original fps from source. + /// + /// Thrown if value is not in valid range + public int Fps + { + get { return _fps; } + set + { + ValidateInputRange(value, 5, 30, "Fps"); + _fps = value; + } + } + + /// + /// Supported audio codecs + /// + public IEnumerable SupportedAudioCodecs + { + get + { + var audioCodecs = new List(); + _handle.ForeachSupportedAudioCodec((codec) => audioCodecs.Add((AudioCodec)codec)); + return audioCodecs; + } + } + + /// + /// Supported video codecs + /// + public IEnumerable SupportedVideoCodecs + { + get + { + var videoCodecs = new List(); + _handle.ForeachSupportedVideoCodec((codec) => videoCodecs.Add((VideoCodec)codec)); + return videoCodecs; + } + } + + /// + /// Supported video file formats + /// + public IEnumerable SupportedVideoFileFormats + { + get + { + var videoFileFormats = new List(); + _handle.ForeachSupportedFileFormat((codec) => videoFileFormats.Add((VideoFileFormat)codec)); + return videoFileFormats; + } + } + + /// + /// Trans-code video + /// + /// Source video file to trans-code + /// Position to start trans-code in seconds + /// Total duration to trans-code, in seconds, if set to 0, trans-coding happens until end of the video + /// Output file path + /// progress update provider + /// Cancellation token, to be used to cancel trans-coding + /// http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage + /// http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage + /// Thrown if application does not have required privilege + /// Thrown if sourceFilePath or outputFile is null + /// Thrown if sourceFilePath does not exist + /// Thrown if video file format is not supported + /// Thrown if Trans-coder is busy trans-coding previous file + /// Thrown if trans-coding is canceled + /// Trans-coding task + public Task TranscodeAsync(string sourceFilePath, ulong startPosition, ulong totalDuration, string outputFile, IProgress progress, CancellationToken cancelToken) + { + ValidateObjectNotDisposed(); + + if (sourceFilePath == null) throw new ArgumentNullException(nameof(sourceFilePath)); + if (outputFile == null) throw new ArgumentNullException(nameof(outputFile)); + + // CAPI does not allow setting properties or start another trans-coding if trans-coder is busy + if (IsBusy) throw new InvalidOperationException("Previous trans-coding is still going on"); + + ConfigureNativeHandle(sourceFilePath); + + var transcodingTask = new TaskCompletionSource(); + if (cancelToken != CancellationToken.None) + { + if (cancelToken.IsCancellationRequested) + { + IsBusy = false; + transcodingTask.TrySetCanceled(); + } + + cancelToken.Register(() => + { + _handle.CancelTranscoding().ThrowIfFailed("Failed to cancel trans-coding"); + IsBusy = false; + transcodingTask.SetResult(false); + }); + } + + Interop.VideoTranscoderHandle.TranscodingProgressCallback progressCb = (currentPosition, duration, userData) => + { + progress?.Report((int)((currentPosition - startPosition) / duration)); + }; + + Interop.VideoTranscoderHandle.TranscodingCompletedCallback completedCb = (errorCode, userData) => + { + if (IsBusy) + { + IsBusy = false; + if (errorCode.IsSuccess()) + { + transcodingTask.TrySetResult(true); + } + else + { + transcodingTask.TrySetException(errorCode.GetException("Failed to trans-code")); + } + } + }; + + var err = _handle.StartTranscoding(startPosition, totalDuration, outputFile, progressCb, completedCb, IntPtr.Zero); + err.ThrowIfFailed("Failed to start trans-coding"); + + IsBusy = !transcodingTask.Task.IsCanceled; + return Interop.PinnedTask(transcodingTask); + } + + /// + /// Trans-code video from start position in input file till end of file. + /// + /// Source video file to trans-code + /// Position to start trans-code in seconds + /// Output file path + /// progress update provider + /// Cancellation token, to be used to cancel trans-coding + /// http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage + /// http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage + /// Thrown if application does not have required privilege + /// Thrown if sourceFilePath or outputFile is null + /// Thrown if sourceFilePath does not exist + /// Thrown if video file format is not supported + /// Thrown if Trans-coder is busy trans-coding previous file + /// Thrown if trans-coding is canceled + /// Trans-coding task + public Task TranscodeAsync(string sourceFilePath, ulong startPosition, string outputFile, IProgress progress, CancellationToken cancelToken) + { + return TranscodeAsync(sourceFilePath, startPosition, 0, outputFile, progress, cancelToken); + } + + /// + /// Trans-code video + /// + /// Source video file to trans-code + /// Position to start trans-code in seconds + /// Total duration to trans-code, in seconds, if set to 0, trans-coding happens until end of the video + /// Output file path + /// progress update provider + /// http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage + /// http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage + /// Thrown if application does not have required privilege + /// Thrown if sourceFilePath or outputFile is null + /// Thrown if sourceFilePath does not exist + /// Thrown if video file format is not supported + /// Thrown if Trans-coder is busy trans-coding previous file + /// Trans-coding task + public Task TranscodeAsync(string sourceFilePath, ulong startPosition, ulong duration, string outputFile, IProgress progress) + { + return TranscodeAsync(sourceFilePath, startPosition, duration, outputFile, progress, CancellationToken.None); + } + + /// + /// Trans-code video + /// + /// Source video file to trans-code + /// Position to start trans-code in seconds + /// Output file path + /// progress update provider + /// http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage + /// http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage + /// Thrown if application does not have required privilege + /// Thrown if sourceFilePath or outputFile is null + /// Thrown if sourceFilePath does not exist + /// Thrown if video file format is not supported + /// Thrown if Trans-coder is busy trans-coding previous file + /// Trans-coding task + public Task TranscodeAsync(string sourceFilePath, ulong startPosition, string outputFile, IProgress progress) + { + return TranscodeAsync(sourceFilePath, startPosition, 0, outputFile, progress, CancellationToken.None); + } + + private void ConfigureNativeHandle(string sourceFilePath) + { + _handle.InputFile = sourceFilePath; + + if (AudioCodec != DetaultAudioCodec) _handle.AudioCodec = (Interop.AudioCodec)AudioCodec; + if (VideoCodec != DetaultVideoCodec) _handle.VideoCodec = (Interop.VideoCodec)VideoCodec; + if (Format != DetaultFileFormat) _handle.FileFormat = (Interop.VideoFileFormat)Format; + if (IsAccurateModeEnabled != DefaultAccurateModeEnabled) _handle.AccurateModeEnabled = IsAccurateModeEnabled; + if (Fps != DefaultFps) _handle.Fps = Fps; + if (Resolution.Width != DefaultResolution.Width || Resolution.Height != DefaultResolution.Height) + { + _handle.SetResolution(Resolution.Width, Resolution.Height).ThrowIfFailed($"Failed to set resolution to {Resolution}"); + } + } + + private void ValidateObjectNotDisposed() + { + if (_disposedValue) + { + throw new ObjectDisposedException(GetType().Name); + } + } + + internal static void ValidateInputRange(T actualValue, T min, T max, string paramName) where T : IComparable + { + if (min.CompareTo(actualValue) == 1 || max.CompareTo(actualValue) == -1) + { + throw new ArgumentOutOfRangeException(paramName, actualValue, $"Valid Range [{min} - {max}]"); + } + } + + internal static void ValidateInputRange(T actualValue, Func verifier, string paramName, string message) + { + if (verifier() == false) + { + throw new ArgumentOutOfRangeException(paramName, actualValue, message); + } + } + + #region IDisposable Support + private bool _disposedValue = false; + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (IsBusy) + { + _handle.CancelTranscoding(); + } + _handle.Dispose(); + _disposedValue = true; + } + } + + public void Dispose() + { + Dispose(true); + } + #endregion + } +} \ No newline at end of file -- 2.7.4