--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using Tizen.Multimedia;
+
+internal static partial class Interop
+{
+ internal static partial class StreamRecorder
+ {
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool VideoResolutionCallback(int width, int height, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool FileFormatCallback(StreamRecorderFileFormat format, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool AudioEncoderCallback(StreamRecorderAudioCodec codec, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool VideoEncoderCallback(StreamRecorderVideoCodec codec, IntPtr userData);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_file_format")]
+ internal static extern StreamRecorderErrorCode FileFormats(StreamRecorderHandle handle,
+ FileFormatCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_audio_encoder")]
+ internal static extern StreamRecorderErrorCode AudioEncoders(StreamRecorderHandle handle,
+ AudioEncoderCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_video_encoder")]
+ internal static extern StreamRecorderErrorCode VideoEncoders(StreamRecorderHandle handle,
+ VideoEncoderCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_video_resolution")]
+ internal static extern StreamRecorderErrorCode VideoResolution(StreamRecorderHandle handle,
+ VideoResolutionCallback callback, IntPtr userData = default(IntPtr));
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using Tizen.Multimedia;
+
+internal static partial class Interop
+{
+ internal static partial class StreamRecorder
+ {
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void RecordingLimitReachedCallback(RecordingLimitType type, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void RecordingStatusCallback(ulong elapsedTime, ulong fileSize, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void NotifiedCallback(int previous, int current,
+ StreamRecorderNotify notify, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void RecorderErrorCallback(StreamRecorderErrorCode error,
+ RecorderState current, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void BufferConsumedCallback(IntPtr buffer, IntPtr userData);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_notify_cb")]
+ internal static extern StreamRecorderErrorCode SetNotifiedCallback(StreamRecorderHandle handle,
+ NotifiedCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_notify_cb")]
+ internal static extern int UnsetNotifiedCallback(StreamRecorderHandle handle);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_recording_status_cb")]
+ internal static extern StreamRecorderErrorCode SetStatusChangedCallback(StreamRecorderHandle handle,
+ RecordingStatusCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_recording_status_cb")]
+ internal static extern int UnsetStatusChangedCallback(StreamRecorderHandle handle);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_recording_limit_reached_cb")]
+ internal static extern StreamRecorderErrorCode SetLimitReachedCallback(StreamRecorderHandle handle,
+ RecordingLimitReachedCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_recording_limit_reached_cb")]
+ internal static extern int UnsetLimitReachedCallback(StreamRecorderHandle handle);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_error_cb")]
+ internal static extern StreamRecorderErrorCode SetErrorCallback(StreamRecorderHandle handle,
+ RecorderErrorCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_error_cb")]
+ internal static extern int UnsetErrorCallback(StreamRecorderHandle handle);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_buffer_consume_completed_cb")]
+ internal static extern StreamRecorderErrorCode SetBufferConsumedCallback(StreamRecorderHandle handle,
+ BufferConsumedCallback callback, IntPtr userData = default(IntPtr));
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_buffer_consume_completed_cb")]
+ internal static extern int UnsetBufferConsumedCallback(StreamRecorderHandle handle);
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using Tizen.Multimedia;
+
+internal static partial class Interop
+{
+ internal static partial class StreamRecorder
+ {
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_filename")]
+ internal static extern StreamRecorderErrorCode SetFileName(StreamRecorderHandle handle, string path);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_filename")]
+ internal static extern int GetFileName(StreamRecorderHandle handle, out IntPtr path);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_file_format")]
+ internal static extern StreamRecorderErrorCode SetFileFormat(StreamRecorderHandle handle,
+ StreamRecorderFileFormat format);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_file_format")]
+ internal static extern int GetFileFormat(StreamRecorderHandle handle, out int format);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_encoder")]
+ internal static extern StreamRecorderErrorCode SetAudioEncoder(StreamRecorderHandle handle,
+ StreamRecorderAudioCodec codec);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_encoder")]
+ internal static extern int GetAudioEncoder(StreamRecorderHandle handle, out int codec);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_encoder")]
+ internal static extern StreamRecorderErrorCode SetVideoEncoder(StreamRecorderHandle handle,
+ StreamRecorderVideoCodec codec);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_encoder")]
+ internal static extern int GetVideoEncoder(StreamRecorderHandle handle, out int codec);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_resolution")]
+ internal static extern StreamRecorderErrorCode SetVideoResolution(StreamRecorderHandle handle,
+ int width, int height);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_resolution")]
+ internal static extern StreamRecorderErrorCode GetVideoResolution(StreamRecorderHandle handle,
+ out int width, out int height);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_framerate")]
+ internal static extern StreamRecorderErrorCode SetVideoFrameRate(StreamRecorderHandle handle, int framerate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_framerate")]
+ internal static extern int GetVideoFramerate(StreamRecorderHandle handle, out int framerate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_source_format")]
+ internal static extern StreamRecorderErrorCode SetVideoSourceFormat(StreamRecorderHandle handle,
+ StreamRecorderVideoFormat format);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_source_format")]
+ internal static extern int GetVideoSourceFormat(StreamRecorderHandle handle, out int format);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_recording_limit")]
+ internal static extern StreamRecorderErrorCode SetRecordingLimit(StreamRecorderHandle handle,
+ RecordingLimitType type, int limit);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_recording_limit")]
+ internal static extern int GetRecordingLimit(StreamRecorderHandle handle, int type, out int format);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_samplerate")]
+ internal static extern StreamRecorderErrorCode SetAudioSampleRate(StreamRecorderHandle handle, int samplerate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_samplerate")]
+ internal static extern int GetAudioSampleRate(StreamRecorderHandle handle, out int samplerate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_encoder_bitrate")]
+ internal static extern StreamRecorderErrorCode SetAudioEncoderBitrate(StreamRecorderHandle handle, int bitrate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_encoder_bitrate")]
+ internal static extern int GetAudioEncoderBitrate(StreamRecorderHandle handle, out int bitrate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_encoder_bitrate")]
+ internal static extern StreamRecorderErrorCode SetVideoEncoderBitRate(StreamRecorderHandle handle, int bitrate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_encoder_bitrate")]
+ internal static extern int GetVideoEncoderBitrate(StreamRecorderHandle handle, out int bitrate);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_channel")]
+ internal static extern StreamRecorderErrorCode SetAudioChannel(StreamRecorderHandle handle, int channel);
+
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_channel")]
+ internal static extern int GetAudioChannel(StreamRecorderHandle handle, out int channel);
+ }
+}
{
internal static partial class StreamRecorder
{
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void RecordingLimitReachedCallback(StreamRecordingLimitType type, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void RecordingStatusCallback(ulong elapsedTime, ulong fileSize, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void NotifiedCallback(StreamRecorderState previous, StreamRecorderState current, StreamRecorderNotify notfication, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void RecorderErrorCallback(StreamRecorderErrorCode error, StreamRecorderState current, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void BufferConsumedCallback(IntPtr buffer, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate bool VideoResolutionCallback(int width, int height, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate bool FileFormatCallback(StreamRecorderFileFormat format, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate bool AudioEncoderCallback(StreamRecorderAudioCodec codec, IntPtr userData);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate bool VideoEncoderCallback(StreamRecorderVideoCodec codec, IntPtr userData);
-
- /* begin of method */
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_create")]
- internal static extern int Create(out IntPtr handle);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_destroy")]
- internal static extern int Destroy(IntPtr handle);
+ internal static extern StreamRecorderErrorCode Create(out StreamRecorderHandle handle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_prepare")]
- internal static extern int Prepare(IntPtr handle);
+ internal static extern StreamRecorderErrorCode Prepare(StreamRecorderHandle handle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unprepare")]
- internal static extern int Unprepare(IntPtr handle);
+ internal static extern StreamRecorderErrorCode Unprepare(StreamRecorderHandle handle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_start")]
- internal static extern int Start(IntPtr handle);
+ internal static extern StreamRecorderErrorCode Start(StreamRecorderHandle handle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_pause")]
- internal static extern int Pause(IntPtr handle);
+ internal static extern StreamRecorderErrorCode Pause(StreamRecorderHandle handle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_commit")]
- internal static extern int Commit(IntPtr handle);
+ internal static extern StreamRecorderErrorCode Commit(StreamRecorderHandle handle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_cancel")]
- internal static extern int Cancel(IntPtr handle);
+ internal static extern StreamRecorderErrorCode Cancel(StreamRecorderHandle handle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_push_stream_buffer")]
- internal static extern int PushStreamBuffer(IntPtr handle, IntPtr/* media_packet_h */ inbuf);
+ internal static extern StreamRecorderErrorCode PushStreamBuffer(StreamRecorderHandle handle,
+ IntPtr mediaPacketHandle);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_enable_source_buffer")]
- internal static extern int EnableSourceBuffer(IntPtr handle, int type);
+ internal static extern StreamRecorderErrorCode EnableSourceBuffer(StreamRecorderHandle handle,
+ StreamRecorderSourceType type);
[DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_state")]
- internal static extern int GetState(IntPtr handle, out int state);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_filename")]
- internal static extern int SetFileName(IntPtr handle, string path);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_filename")]
- internal static extern int GetFileName(IntPtr handle, out IntPtr path);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_file_format")]
- internal static extern int SetFileFormat(IntPtr handle, int format);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_file_format")]
- internal static extern int GetFileFormat(IntPtr handle, out int format);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_encoder")]
- internal static extern int SetAudioEncoder(IntPtr handle, int codec);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_encoder")]
- internal static extern int GetAudioEncoder(IntPtr handle, out int codec);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_encoder")]
- internal static extern int SetVideoEncoder(IntPtr handle, int codec);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_encoder")]
- internal static extern int GetVideoEncoder(IntPtr handle, out int codec);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_resolution")]
- internal static extern int SetVideoResolution(IntPtr handle, int width, int height);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_resolution")]
- internal static extern int GetVideoResolution(IntPtr handle, out int width, out int height);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_framerate")]
- internal static extern int SetVideoFramerate(IntPtr handle, int framerate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_framerate")]
- internal static extern int GetVideoFramerate(IntPtr handle, out int framerate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_source_format")]
- internal static extern int SetVideoSourceFormat(IntPtr handle, int format);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_source_format")]
- internal static extern int GetVideoSourceFormat(IntPtr handle, out int format);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_recording_limit")]
- internal static extern int SetRecordingLimit(IntPtr handle, int type, int limit);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_recording_limit")]
- internal static extern int GetRecordingLimit(IntPtr handle, int type, out int format);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_samplerate")]
- internal static extern int SetAudioSampleRate(IntPtr handle, int samplerate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_samplerate")]
- internal static extern int GetAudioSampleRate(IntPtr handle, out int samplerate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_encoder_bitrate")]
- internal static extern int SetAudioEncoderBitrate(IntPtr handle, int bitrate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_encoder_bitrate")]
- internal static extern int GetAudioEncoderBitrate(IntPtr handle, out int bitrate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_video_encoder_bitrate")]
- internal static extern int SetVideoEncoderBitrate(IntPtr handle, int bitrate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_video_encoder_bitrate")]
- internal static extern int GetVideoEncoderBitrate(IntPtr handle, out int bitrate);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_audio_channel")]
- internal static extern int SetAudioChannel(IntPtr handle, int channel);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_get_audio_channel")]
- internal static extern int GetAudioChannel(IntPtr handle, out int channel);
- /* End of method */
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_file_format")]
- internal static extern int FileFormats(IntPtr handle, FileFormatCallback callback, IntPtr userData);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_audio_encoder")]
- internal static extern int AudioEncoders(IntPtr handle, AudioEncoderCallback callback, IntPtr userData);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_video_encoder")]
- internal static extern int VideoEncoders(IntPtr handle, VideoEncoderCallback callback, IntPtr userData);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_foreach_supported_video_resolution")]
- internal static extern int VideoResolution(IntPtr handle, VideoResolutionCallback callback, IntPtr userData);
- /* End of foreach method */
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_notify_cb")]
- internal static extern int SetNotifiedCallback(IntPtr handle, NotifiedCallback callback, IntPtr userData);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_notify_cb")]
- internal static extern int UnsetNotifiedCallback(IntPtr handle);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_recording_status_cb")]
- internal static extern int SetStatusChangedCallback(IntPtr handle, RecordingStatusCallback callback, IntPtr userData);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_recording_status_cb")]
- internal static extern int UnsetStatusChangedCallback(IntPtr handle);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_recording_limit_reached_cb")]
- internal static extern int SetLimitReachedCallback(IntPtr handle, RecordingLimitReachedCallback callback, IntPtr userData);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_recording_limit_reached_cb")]
- internal static extern int UnsetLimitReachedCallback(IntPtr handle);
-
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_error_cb")]
- internal static extern int SetErrorCallback(IntPtr handle, RecorderErrorCallback callback, IntPtr userData);
+ internal static extern StreamRecorderErrorCode GetState(StreamRecorderHandle handle, out RecorderState state);
+ }
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_error_cb")]
- internal static extern int UnsetErrorCallback(IntPtr handle);
+ internal class StreamRecorderHandle : SafeHandle
+ {
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_destroy")]
+ private static extern StreamRecorderErrorCode Destroy(IntPtr handle);
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_set_buffer_consume_completed_cb")]
- internal static extern int SetBufferConsumedCallback(IntPtr handle, BufferConsumedCallback callback, IntPtr userDat);
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_cancel")]
+ private static extern StreamRecorderErrorCode Cancel(IntPtr handle);
- [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unset_buffer_consume_completed_cb")]
- internal static extern int UnsetBufferConsumedCallback(IntPtr handle);
+ [DllImport(Libraries.StreamRecorder, EntryPoint = "streamrecorder_unprepare")]
+ private static extern StreamRecorderErrorCode Unprepare(IntPtr handle);
+
+ protected StreamRecorderHandle() : base(IntPtr.Zero, true)
+ {
+ }
+
+ public override bool IsInvalid => handle == IntPtr.Zero;
+
+ protected override bool ReleaseHandle()
+ {
+ try
+ {
+ Cancel(handle).Ignore(StreamRecorderErrorCode.InvalidState).ThrowIfError("Failed to cancel.");
+ Unprepare(handle).Ignore(StreamRecorderErrorCode.InvalidState).ThrowIfError("Failed to unprepare.");
+ Destroy(handle).ThrowIfError("Failed to destory.");
+
+ return true;
+ }
+ catch (Exception e)
+ {
+ Tizen.Log.Debug(GetType().FullName, $"Failed to release native RecorderHandle; {e.Message}");
+
+ return false;
+ }
+ }
}
}
--- /dev/null
+/*
+ * 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.Linq;
+using Native = Interop.StreamRecorder;
+
+namespace Tizen.Multimedia
+{
+ public partial class StreamRecorder
+ {
+ internal void LoadCapabilities()
+ {
+ _videoCodecs = LoadVideoCodecs(this);
+ _audioCodecs = LoadAudioCodecs(this);
+ _fileFormats = LoadFileFormats(this);
+ _videoResolutions = LoadResolutions(this);
+ }
+
+ private static IEnumerable<RecorderVideoCodec> LoadVideoCodecs(StreamRecorder recorder)
+ {
+ var result = new List<RecorderVideoCodec>();
+ Native.VideoEncoderCallback callback = (codec, _) =>
+ {
+ result.Add(codec.ToRecorderEnum());
+ return true;
+ };
+
+ Native.VideoEncoders(recorder.Handle, callback).ThrowIfError("Failed to get the supported video codecs.");
+
+ return result.AsReadOnly();
+ }
+
+ private static IEnumerable<RecorderAudioCodec> LoadAudioCodecs(StreamRecorder recorder)
+ {
+ var result = new List<RecorderAudioCodec>();
+
+ Native.AudioEncoders(recorder.Handle, (codec, _) =>
+ {
+ result.Add(codec.ToRecorderEnum());
+ return true;
+ }).ThrowIfError("Failed to get the supported audio codecs.");
+
+ return result.AsReadOnly();
+ }
+
+ private static IEnumerable<RecorderFileFormat> LoadFileFormats(StreamRecorder recorder)
+ {
+ var result = new List<RecorderFileFormat>();
+
+ Native.FileFormats(recorder.Handle, (fileFormat, _) =>
+ {
+ result.Add(fileFormat.ToRecorderEnum());
+ return true;
+ }).ThrowIfError("Failed to get the supported file formats.");
+
+ return result.AsReadOnly();
+ }
+
+ private static IEnumerable<Size> LoadResolutions(StreamRecorder recorder)
+ {
+ List<Size> result = new List<Size>();
+
+ Native.VideoResolutionCallback callback = (width, height, _) =>
+ {
+ result.Add(new Size(width, height));
+ return true;
+ };
+
+ Native.VideoResolution(recorder.Handle, callback).
+ ThrowIfError("Failed to get the supported video resolutions.");
+
+ return result.AsReadOnly();
+ }
+
+ private IEnumerable<RecorderFileFormat> _fileFormats;
+
+ /// <summary>
+ /// Gets the file formats that the current device supports.
+ /// </summary>
+ /// <returns>An IEnumerable of <see cref="RecorderFileFormat"/> representing the supported file formats.</returns>
+ public IEnumerable<RecorderFileFormat> GetSupportedFileFormats() => _fileFormats;
+
+ private IEnumerable<RecorderAudioCodec> _audioCodecs;
+
+ /// <summary>
+ /// Gets the audio codecs that the current device supports.
+ /// </summary>
+ /// <returns>An IEnumerable of <see cref="RecorderAudioCodec"/> representing the supported audio codecs.</returns>
+ public IEnumerable<RecorderAudioCodec> GetSupportedAudioCodecs() => _audioCodecs;
+
+ private IEnumerable<RecorderVideoCodec> _videoCodecs;
+
+ /// <summary>
+ /// Gets the video codecs that the current device supports.
+ /// </summary>
+ /// <returns>An IEnumerable of <see cref="RecorderVideoCodec"/> representing the supported video codecs.</returns>
+ public IEnumerable<RecorderVideoCodec> GetSupportedVideoCodecs() => _videoCodecs;
+
+ private IEnumerable<Size> _videoResolutions;
+
+ /// <summary>
+ /// Gets the video resolutions that the current device supports.
+ /// </summary>
+ /// <returns>An IEnumerable of <see cref="Size"/> representing the supported resolutions.</returns>
+ public IEnumerable<Size> GetSupportedVideoResolutions() => _videoResolutions;
+
+ internal void ValidateFileFormat(RecorderFileFormat format)
+ {
+ if (_fileFormats.Contains(format) == false)
+ {
+ throw new NotSupportedException($"{format.ToString()} is not supported.");
+ }
+ }
+
+ internal void ValidateAudioCodec(RecorderAudioCodec codec)
+ {
+ if (_audioCodecs.Contains(codec) == false)
+ {
+ throw new NotSupportedException($"{codec.ToString()} is not supported.");
+ }
+ }
+
+ internal void ValidateVideoCodec(RecorderVideoCodec codec)
+ {
+ if (_videoCodecs.Contains(codec) == false)
+ {
+ throw new NotSupportedException($"{codec.ToString()} is not supported.");
+ }
+ }
+
+ internal void ValidateVideoResolution(Size resolution)
+ {
+ if (_videoResolutions.Contains(resolution) == false)
+ {
+ throw new NotSupportedException($"Resolution({resolution.ToString()}) is not supported.");
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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 Native = Interop.StreamRecorder;
+
+namespace Tizen.Multimedia
+{
+ public partial class StreamRecorder
+ {
+ /// <summary>
+ /// Occurs when <see cref="StreamRecorder"/> state is changed.
+ /// </summary>
+ public event EventHandler<StreamRecorderStateChangedEventArgs> StateChanged;
+
+
+ /// <summary>
+ /// Occurs when a buffer had consumed completely.
+ /// </summary>
+ public event EventHandler<StreamRecorderBufferConsumedEventArgs> BufferConsumed;
+
+ /// <summary>
+ /// Occurs when recording status is changed.
+ /// </summary>
+ public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged;
+
+ /// <summary>
+ /// Occurs when recording limit is reached.
+ /// </summary>
+ public event EventHandler<RecordingLimitReachedEventArgs> RecordingLimitReached;
+
+ /// <summary>
+ /// Occurs when an error occurred during a recorder operation.
+ /// </summary>
+ public event EventHandler<StreamRecorderErrorOccurredEventArgs> ErrorOccurred;
+
+ private Native.RecordingLimitReachedCallback _recordingLimitReachedCallback;
+ private Native.RecorderErrorCallback _recorderErrorCallback;
+ private Native.RecordingStatusCallback _recordingStatusCallback;
+ private Native.BufferConsumedCallback _bufferConsumedCallback;
+ private Native.NotifiedCallback _notifiedCallback;
+
+ private void RegisterStreamRecorderNotifiedEvent()
+ {
+ _notifiedCallback = (previous, current, notify, _) =>
+ {
+ if (previous == 0)
+ {
+ return;
+ }
+
+ StateChanged?.Invoke(this, new StreamRecorderStateChangedEventArgs(
+ (RecorderState)previous, (RecorderState)current));
+ };
+
+ Native.SetNotifiedCallback(_handle, _notifiedCallback).
+ ThrowIfError("Failed to initialize state changed event.");
+ }
+
+ private void RegisterBufferConsumedEvent()
+ {
+ _bufferConsumedCallback = (lockedPacketHandle, _) =>
+ {
+ MediaPacket packet = null;
+
+ // Lock must be disposed here, note that the packet won't be disposed.
+ using (MediaPacket.Lock packetLock =
+ MediaPacket.Lock.FromHandle(lockedPacketHandle))
+ {
+ Debug.Assert(packetLock != null);
+
+ packet = packetLock.MediaPacket;
+ }
+
+ BufferConsumed?.Invoke(this, new StreamRecorderBufferConsumedEventArgs(packet));
+ };
+
+ Native.SetBufferConsumedCallback(_handle, _bufferConsumedCallback).
+ ThrowIfError("Failed to initialize buffer consumed event.");
+ }
+
+ private void RegisterRecordingStatusChangedEvent()
+ {
+ _recordingStatusCallback = (elapsedTime, fileSize, _) =>
+ {
+ RecordingStatusChanged?.Invoke(this, new RecordingStatusChangedEventArgs((long)elapsedTime, (long)fileSize));
+ };
+ Native.SetStatusChangedCallback(_handle, _recordingStatusCallback).
+ ThrowIfError("Failed to initialize status changed event.");
+ }
+
+ private void RegisterRecordingLimitReachedEvent()
+ {
+ _recordingLimitReachedCallback = (type, _) =>
+ {
+ RecordingLimitReached?.Invoke(this, new RecordingLimitReachedEventArgs(type));
+ };
+
+ Native.SetLimitReachedCallback(_handle, _recordingLimitReachedCallback).
+ ThrowIfError("Failed to initialize limit reached event.");
+ }
+
+ private void RegisterRecordingErrorOccurredEvent()
+ {
+ _recorderErrorCallback = (error, currentState, _) =>
+ {
+ ErrorOccurred?.Invoke(this, new StreamRecorderErrorOccurredEventArgs(
+ error == StreamRecorderErrorCode.OutOfStorage ?
+ StreamRecorderError.OutOfStorage : StreamRecorderError.InternalError, currentState));
+ };
+ Native.SetErrorCallback(_handle, _recorderErrorCallback).
+ ThrowIfError("Failed to set error callback");
+ }
+ }
+}
*/
using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using Tizen.Internals.Errors;
+using System.Diagnostics;
+using System.Linq;
+using NativeHandle = Interop.StreamRecorderHandle;
using Native = Interop.StreamRecorder;
namespace Tizen.Multimedia
{
- static internal class StreamRecorderLog
- {
- internal const string Tag = "Tizen.Multimedia.StreamRecorder";
- }
-
/// <summary>
- /// Provides methods to control stream recorder.
+ /// Provides the ability to record user buffer from application.
/// </summary>
- /// <remarks>
- /// StreamRecorder class provides functions to record raw image frame
- /// also provides recording start, stop and save the content etc.
- /// </remarks>
- public class StreamRecorder : IDisposable
+ /// <seealso cref="Recorder"/>
+ public partial class StreamRecorder : IDisposable
{
- private IntPtr _handle;
+ private NativeHandle _handle;
private bool _disposed = false;
- /// <summary>
- /// Occurred when recording is progressing for recording status.
- /// </summary>
- private EventHandler<RecordingStatusChangedEventArgs> _recordingStatusChanged;
- private Native.RecordingStatusCallback _recordingStatusCallback;
- /// <summary>
- /// Occurred when recording time or size reach limit.
- /// </summary>
- private EventHandler<StreamRecordingLimitReachedEventArgs> _recordingLimitReached;
- private Native.RecordingLimitReachedCallback _recordingLimitReachedCallback;
- /// <summary>
- /// Occurred when streamrecorder complete to use pushed buffer.
- /// </summary>
- private EventHandler<StreamRecordingBufferConsumedEventArgs> _bufferConsumed;
- private Native.BufferConsumedCallback _bufferConsumedCallback;
- /// <summary>
- /// Occurred when streamrecorder state is changed.
- /// </summary>
- private EventHandler<StreamRecorderNotifiedEventArgs> _recorderNotified;
- private Native.NotifiedCallback _notifiedCallback;
- /// <summary>
- /// Occurred when error is occured.
- /// </summary>
- private EventHandler<StreamRecordingErrorOccurredEventArgs> _recordingErrorOccurred;
- private Native.RecorderErrorCallback _recorderErrorCallback;
- private List<StreamRecorderFileFormat> _formats;
- private List<StreamRecorderAudioCodec> _audioCodec;
- private List<StreamRecorderVideoCodec> _videoCodec;
- private List<StreamRecorderVideoResolution> _resolutions;
- StreamRecorderVideoResolution _videoResolution = null;
+ private bool _audioEnabled;
+ private bool _videoEnabled;
+ private StreamRecorderVideoFormat _sourceFormat;
/// <summary>
- /// Stream recorder constructor.
+ /// Initialize a new instance of the <see cref="StreamRecorder"/> class.
/// </summary>
+ /// <exception cref="NotSupportedException">The feature is not supported.</exception>
public StreamRecorder()
{
- int ret = Native.Create(out _handle);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to create stream recorder");
- }
- _formats = new List<StreamRecorderFileFormat>();
- _audioCodec = new List<StreamRecorderAudioCodec>();
- _videoCodec = new List<StreamRecorderVideoCodec>();
- _resolutions = new List<StreamRecorderVideoResolution>();
- _videoResolution = new StreamRecorderVideoResolution(_handle);
- }
-
- /// <summary>
- /// Stream recorder destructor.
- /// </summary>
- ~StreamRecorder()
- {
- Dispose(false);
- }
-
- /// <summary>
- /// Event that occurs when streamrecorder state is changed.
- /// </summary>
- public event EventHandler<StreamRecorderNotifiedEventArgs> RecorderNotified
- {
- add
- {
- if (_recorderNotified == null)
- {
- RegisterStreamRecorderNotifiedEvent();
- }
- _recorderNotified += value;
- }
- remove
- {
- _recorderNotified -= value;
- if (_recorderNotified == null)
- {
- UnregisterStreamRecorderNotifiedEvent();
- }
- }
- }
-
- /// <summary>
- /// Event that occurs when buffer had comsumed completely.
- /// </summary>
- public event EventHandler<StreamRecordingBufferConsumedEventArgs> BufferConsumed
- {
- add
+ try
{
- if (_bufferConsumed == null)
- {
- RegisterBufferComsumedEvent();
- }
- _bufferConsumed += value;
+ Native.Create(out _handle).ThrowIfError("Failed to create stream recorder.");
}
- remove
+ catch (TypeLoadException)
{
- _bufferConsumed -= value;
- if (_bufferConsumed == null)
- {
- UnregisterBufferComsumedEvent();
- }
- }
- }
-
- /// <summary>
- /// Event that occurs when recording status changed.
- /// </summary>
- public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged
- {
- add
- {
- if (_recordingStatusChanged == null)
- {
- RegisterRecordingStatusChangedEvent();
- }
- _recordingStatusChanged += value;
- }
- remove
- {
- _recordingStatusChanged -= value;
- if (_recordingStatusChanged == null)
- {
- UnregisterRecordingStatusChangedEvent();
- }
+ throw new NotSupportedException("StreamRecorder is not supported.");
}
- }
- /// <summary>
- /// Event that occurs when recording limit is reached.
- /// </summary>
- public event EventHandler<StreamRecordingLimitReachedEventArgs> RecordingLimitReached
- {
- add
- {
- if (_recordingLimitReached == null)
- {
- RegisterRecordingLimitReachedEvent();
- }
- _recordingLimitReached += value;
- }
- remove
- {
- _recordingLimitReached -= value;
- if (_recordingLimitReached == null)
- {
- UnregisterRecordingLimitReachedEvent();
- }
- }
- }
+ LoadCapabilities();
- /// <summary>
- /// Event that occurs when an error occured during recorder operation.
- /// </summary>
- public event EventHandler<StreamRecordingErrorOccurredEventArgs> RecordingErrorOccurred
- {
- add
- {
- if (_recordingErrorOccurred == null)
- {
- RegisterRecordingErrorOccurredEvent();
- }
- _recordingErrorOccurred += value;
- }
- remove
- {
- _recordingErrorOccurred -= value;
- if (_recordingErrorOccurred == null)
- {
- UnregisterRecordingErrorOccurredEvent();
- }
- }
+ RegisterStreamRecorderNotifiedEvent();
+ RegisterBufferConsumedEvent();
+ RegisterRecordingStatusChangedEvent();
+ RegisterRecordingErrorOccurredEvent();
+ RegisterRecordingLimitReachedEvent();
}
- /// <summary>
- /// The file path to record.
- /// </summary>
- /// <remarks>
- /// If the same file already exists in the file system, then old file
- /// will be overwritten.
- /// </remarks>
- public string FilePath
+ internal NativeHandle Handle
{
get
{
- IntPtr val;
- int ret = Native.GetFileName(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
+ if (_disposed)
{
- Log.Error(StreamRecorderLog.Tag, "Failed to get filepath, " + (StreamRecorderError)ret);
+ throw new ObjectDisposedException(nameof(StreamRecorder));
}
- string result = Marshal.PtrToStringAnsi(val);
- LibcSupport.Free(val);
- return result;
- }
- set
- {
- int ret = Native.SetFileName(_handle, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set filepath, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set filepath");
- }
- }
- }
-
- /// <summary>
- /// Get the current state of the stream recorder.
- /// </summary>
- /// <value> The current state of stream recorder.
- public StreamRecorderState State
- {
- get
- {
- int val = 0;
- int ret = Native.GetState(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get stream recorder state, " + (StreamRecorderError)ret);
- }
- return (StreamRecorderState)val;
+ return _handle;
}
}
/// <summary>
- /// Get/Set the file format for recording media stream.
+ /// Gets the current state of the stream recorder.
/// </summary>
- /// <remarks>
- /// Must set <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>.
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// </remarks>
- /// <exception cref="ArgumentException">The format does not valid.</exception>
- /// <seealso cref="SupportedFileFormats"/>
- public StreamRecorderFileFormat FileFormat
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
+ public RecorderState State
{
get
{
- int val = 0;
-
- int ret = Native.GetFileFormat(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get file format, " + (StreamRecorderError)ret);
- }
- return (StreamRecorderFileFormat)val;
- }
- set
- {
- int ret = Native.SetFileFormat(_handle, (int)value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set file format, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret);
- }
- }
- }
+ Native.GetState(Handle, out var val).ThrowIfError("Failed to get the stream recorder state.");
- /// <summary>
- /// The audio codec for encoding an audio stream.
- /// </summary>
- /// <remarks>
- /// Must set <see cref="StreamRecorderSourceType.Audio"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
- /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
- /// </remarks>
- /// <exception cref="ArgumentException">The codec does not valid.</exception>
- /// <seealso cref="SupportedAudioEncodings"/>
- public StreamRecorderAudioCodec AudioCodec
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetAudioEncoder(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get audio codec, " + (StreamRecorderError)ret);
- }
- return (StreamRecorderAudioCodec)val;
- }
- set
- {
- int ret = Native.SetAudioEncoder(_handle, (int)value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set audio codec, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret);
- }
- }
- }
-
- /// <summary>
- /// The video codec for encoding video stream.
- /// </summary>
- /// <remarks>
- /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
- /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
- /// </remarks>
- /// <exception cref="ArgumentException">The codec does not valid.</exception>
- /// <seealso cref="SupportedVideoEncodings"/>
- public StreamRecorderVideoCodec VideoCodec
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetVideoEncoder(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get video codec, " + (StreamRecorderError)ret);
- }
- return (StreamRecorderVideoCodec)val;
- }
- set
- {
- int ret = Native.SetVideoEncoder(_handle, (int)value);
-
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set video codec, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret);
- }
- }
- }
-
- /// <summary>
- /// The maximum size of a recording file in KB(kilobytes). If 0, means
- /// unlimited recording size.
- /// </summary>
- /// <remarks>
- /// After reaching the limitation, the data which is being recorded will
- /// be discarded and not written to the file.
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// </remarks>
- /// <exception cref="ArgumentException">The value set to below 0.</exception>
- /// <seealso cref="StreamRecordingLimitReachedEventArgs"/>
- public int SizeLimit
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetRecordingLimit(_handle, 1, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get size limit, " + (StreamRecorderError)ret);
- }
return val;
}
- set
- {
- int ret = Native.SetRecordingLimit(_handle, 1, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set sizelimit, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set size limit");
- }
- }
}
- /// <summary>
- /// The time limit of a recording file in Seconds. If 0, means unlimited recording
- /// time.
- /// </summary>
- /// <remarks>
- /// After reaching the limitation, the data which is being recorded will
- /// be discarded and not written to the file.
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// </remarks>
- /// <exception cref="ArgumentException">The value set to below 0.</exception>
- /// <seealso cref="StreamRecordingLimitReachedEventArgs"/>
- public int TimeLimit
+ private void ValidateState(params RecorderState[] required)
{
- get
- {
- int val = 0;
+ Debug.Assert(required.Length > 0);
- int ret = Native.GetRecordingLimit(_handle, 0, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get time limit, " + (StreamRecorderError)ret);
- }
- return val;
- }
- set
+ var curState = State;
+ if (!required.Contains(curState))
{
- int ret = Native.SetRecordingLimit(_handle, 0, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set timelimit, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set time limit");
- }
+ throw new InvalidOperationException($"The stream recorder is not in a valid state. " +
+ $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
}
}
+ #region Operation methods
/// <summary>
- /// The sampling rate of an audio stream in hertz.
+ /// Prepares the stream recorder with the specified options.
/// </summary>
- /// <remarks>
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// Must set <see cref="StreamRecorderSourceType.Audio"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
- /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>.
- /// </remarks>
- /// <exception cref="ArgumentException">The value set to below 0.</exception>
- public int AudioSampleRate
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetAudioSampleRate(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get audio samplerate, " + (StreamRecorderError)ret);
- }
- return val;
- }
- set
- {
- int ret = Native.SetAudioSampleRate(_handle, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set audio samplerate, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set audio samplerate");
- }
- }
- }
-
- /// <summary>
- /// The bitrate of an audio encoder in bits per second.
- /// </summary>
- /// <remarks>
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// Must set <see cref="StreamRecorderSourceType.Audio"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
- /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
- /// </remarks>
- /// <exception cref="ArgumentException">The value set to below 0.</exception>
- public int AudioBitRate
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetAudioEncoderBitrate(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get audio bitrate, " + (StreamRecorderError)ret);
- }
- return val;
- }
- set
- {
- int ret = Native.SetAudioEncoderBitrate(_handle, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set audio bitrate, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set audio bitrate");
- }
- }
- }
-
- /// <summary>
- /// The bitrate of an video encoder in bits per second.
- /// </summary>
- /// <remarks>
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
- /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
- /// </remarks>
- /// <exception cref="ArgumentException">The value set to below 0.</exception>
- public int VideoBitRate
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetVideoEncoderBitrate(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get video bitrate, " + (StreamRecorderError)ret);
- }
- return val;
- }
- set
- {
- int ret = Native.SetVideoEncoderBitrate(_handle, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set video bitrate, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set video bitrate");
- }
- }
- }
-
- /// <summary>
- /// The video frame rate for recording media stream.
- /// </summary>
- /// <remarks>
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
- /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
- /// </remarks>
- /// <exception cref="NotSupportedException">The value set to below 0.</exception>
- public int VideoFrameRate
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetVideoFramerate(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get video framerate, " + (StreamRecorderError)ret);
- }
- return val;
- }
- set
- {
- int ret = Native.SetVideoFramerate(_handle, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set video framerate, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret);
- }
- }
- }
-
- /// <summary>
- /// Get or Set the video source format for recording media stream.
- /// </summary>
- /// <exception cref="ArgumentException">The value set to a invalid value.</exception>
- /// <seealso cref="StreamRecorderVideoSourceFormat"/>
- public StreamRecorderVideoSourceFormat VideoSourceFormat
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetVideoSourceFormat(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get video framerate, " + (StreamRecorderError)ret);
- }
- return (StreamRecorderVideoSourceFormat)val;
- }
- set
- {
- int ret = Native.SetVideoSourceFormat(_handle, (int)value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set video framerate, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret);
- }
- }
- }
-
- /// <summary>
- /// The number of audio channel.
- /// </summary>
- /// <remarks>
- /// The attribute is applied only in Created state.
- /// For mono recording, set channel to 1.
- /// For stereo recording, set channel to 2.
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// </remarks>
- /// <exception cref="ArgumentException">The value set to a invalid value.</exception>
- public int AudioChannel
- {
- get
- {
- int val = 0;
-
- int ret = Native.GetAudioChannel(_handle, out val);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to get audio channel, " + (StreamRecorderError)ret);
- }
- return val;
- }
- set
- {
- int ret = Native.SetAudioChannel(_handle, value);
- if ((StreamRecorderError)ret != StreamRecorderError.None)
- {
- Log.Error(StreamRecorderLog.Tag, "Failed to set audio channel, " + (StreamRecorderError)ret);
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set audio channel");
- }
- }
- }
-
- /// <summary>
- /// Video resolution of the video recording.
- /// </summary>
- /// <remarks>
- /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
- /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
- /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
- /// </remarks>
- /// <exception cref="ArgumentException">The value set to a invalid value.</exception>
- /// <seealso cref="SupportedVideoResolutions"/>
- public StreamRecorderVideoResolution Resolution
+ /// <remarks>The recorder must be <see cref="RecorderState.Idle"/>.</remarks>
+ /// <param name="options">The options for recording.</param>
+ /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+ /// <exception cref="ArgumentException">Both <see cref="StreamRecorderOptions.Audio"/> and
+ /// <see cref="StreamRecorderOptions.Video"/> are null.
+ /// </exception>
+ /// <exception cref="NotSupportedException"><paramref name="options"/> contains a value which is not supported.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
+ /// <seealso cref="Unprepare"/>
+ /// <seealso cref="Start"/>
+ /// <seealso cref="StreamRecorderOptions"/>
+ /// <seealso cref="StreamRecorderAudioOptions"/>
+ /// <seealso cref="StreamRecorderVideoOptions"/>
+ public void Prepare(StreamRecorderOptions options)
{
- get
+ if (options == null)
{
- return _videoResolution;
+ throw new ArgumentNullException(nameof(options));
}
- }
- /// <summary>
- /// Retrieves all the file formats supported by the stream recorder.
- /// </summary>
- /// <returns>
- /// It returns a list containing all the supported file
- /// formats by Stream recorder.
- /// </returns>
- /// <seealso cref="StreamRecorderFileFormat"/>
- public IEnumerable<StreamRecorderFileFormat> SupportedFileFormats
- {
- get
- {
- if (_formats.Count == 0)
- {
- Native.FileFormatCallback callback = (StreamRecorderFileFormat format, IntPtr userData) =>
- {
- _formats.Add(format);
- return true;
- };
- int ret = Native.FileFormats(_handle, callback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported fileformats");
- }
- }
- return _formats;
- }
- }
+ ValidateState(RecorderState.Idle);
- /// <summary>
- /// Retrieves all the audio encoders supported by the recorder.
- /// </summary>
- /// <returns>
- /// It returns a list containing all the supported audio encoders
- /// by recorder.
- /// </returns>
- /// <seealso cref="StreamRecorderAudioCodec"/>
- public IEnumerable<StreamRecorderAudioCodec> SupportedAudioEncodings
- {
- get
- {
- if (_audioCodec.Count == 0)
- {
- Native.AudioEncoderCallback callback = (StreamRecorderAudioCodec codec, IntPtr userData) =>
- {
- _audioCodec.Add(codec);
- return true;
- };
- int ret = Native.AudioEncoders(_handle, callback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported audio encoders");
- }
- }
- return _audioCodec;
- }
- }
+ options.Apply(this);
- /// <summary>
- /// Retrieves all the video encoders supported by the recorder.
- /// </summary>
- /// <returns>
- /// It returns a list containing all the supported video encoders
- /// by recorder.
- /// </returns>
- /// <seealso cref="StreamRecorderVideoCodec"/>
- public IEnumerable<StreamRecorderVideoCodec> SupportedVideoEncodings
- {
- get
- {
- if (_videoCodec.Count == 0)
- {
- Native.VideoEncoderCallback callback = (StreamRecorderVideoCodec codec, IntPtr userData) =>
- {
- _videoCodec.Add(codec);
- return true;
- };
- int ret = Native.VideoEncoders(_handle, callback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported video encoders");
- }
- }
- return _videoCodec;
- }
- }
+ Native.Prepare(Handle).ThrowIfError("Failed to prepare stream recorder.");
- /// <summary>
- /// Retrieves all the video resolutions supported by the recorder.
- /// </summary>
- /// <returns>
- /// It returns videoresolution list containing the width and height of
- /// different resolutions supported by recorder.
- /// </returns>
- /// <seealso cref="StreamRecorderVideoResolution"/>
- public IEnumerable<StreamRecorderVideoResolution> SupportedVideoResolutions
- {
- get
- {
- if (_resolutions.Count == 0)
- {
- Native.VideoResolutionCallback callback = (int width, int height, IntPtr userData) =>
- {
- StreamRecorderVideoResolution temp = new StreamRecorderVideoResolution(width, height);
- _resolutions.Add(temp);
- return true;
- };
- int ret = Native.VideoResolution(_handle, callback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported video resolutions");
- }
- }
- return _resolutions;
- }
- }
+ _audioEnabled = options.Audio != null;
+ _videoEnabled = options.Video != null;
- /// <summary>
- /// Prepare the stream recorder.
- /// </summary>
- /// <remarks>
- /// Before calling the function, it is required to set <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>,
- /// <see cref="StreamRecorderAudioCodec"/>, <see cref="StreamRecorderVideoCodec"/> and <see cref="StreamRecorderFileFormat"/> properties of recorder.
- /// </remarks>
- /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
- /// <seealso cref="Unprepare"/>
- public void Prepare()
- {
- int ret = Native.Prepare(_handle);
- if (ret != (int)StreamRecorderError.None)
+ if (options.Video != null)
{
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to prepare stream recorder");
+ _sourceFormat = options.Video.SourceFormat;
}
}
/// <summary>
- /// Resets the stream recorder.
+ /// Unprepares the stream recorder.
/// </summary>
/// <remarks>
- /// The recorder state must be <see cref="StreamRecorderState.Prepared"/> state by <see cref="Prepare"/>, <see cref="Cancel"/> and <see cref="Commit"/>.
- /// The StreamRecorder state will be <see cref="StreamRecorderState.Created"/>.
+ /// The recorder state must be <see cref="RecorderState.Ready"/> state by
+ /// <see cref="Prepare(StreamRecorderOptions)"/>, <see cref="Cancel"/> and <see cref="Commit"/>.\n
+ /// The recorder state will be <see cref="RecorderState.Idle"/>.\n
+ /// \n
+ /// It has no effect if the recorder is already in the <see cref="RecorderState.Idle"/> state.
/// </remarks>
- /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
+ /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
/// <seealso cref="Prepare"/>
public void Unprepare()
{
- int ret = Native.Unprepare(_handle);
- if (ret != (int)StreamRecorderError.None)
+ if (State == RecorderState.Idle)
{
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to reset the stream recorder");
+ return;
}
+
+ ValidateState(RecorderState.Ready);
+
+ Native.Unprepare(Handle).ThrowIfError("Failed to reset the stream recorder.");
}
/// <summary>
- /// Starts the recording.
+ /// Starts recording.
/// </summary>
/// <remarks>
- /// If file path has been set to an existing file, this file is removed automatically and updated by new one.
- /// The filename should be set before this function is invoked.
- /// The recorder state must be <see cref="StreamRecorderState.Prepared"/> state by <see cref="Prepare"/> or
- /// <see cref="StreamRecorderState.Paused"/> state by <see cref="Pause"/>.
- /// The filename shuild be set by <see cref="FilePath"/>
+ /// The recorder state must be <see cref="RecorderState.Ready"/> state by
+ /// <see cref="Prepare(StreamRecorderOptions)"/> or
+ /// <see cref="RecorderState.Paused"/> state by <see cref="Pause"/>.\n
+ /// \n
+ /// It has no effect if the recorder is already in the <see cref="RecorderState.Recording"/> state.
/// </remarks>
- /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
- /// <exception cref="UnauthorizedAccessException">The access ot the resources can not be granted.</exception>
+ /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+ /// <exception cref="UnauthorizedAccessException">The access of the resources can not be granted.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
/// <seealso cref="Pause"/>
/// <seealso cref="Commit"/>
/// <seealso cref="Cancel"/>
- /// <seealso cref="FilePath"/>
- /// <seealso cref="FileFormat"/>
public void Start()
{
- int ret = Native.Start(_handle);
- if (ret != (int)StreamRecorderError.None)
+ if (State == RecorderState.Recording)
{
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to start the stream recorder");
+ return;
}
+
+ ValidateState(RecorderState.Ready, RecorderState.Paused);
+
+ Native.Start(Handle).ThrowIfError("Failed to start the stream recorder.");
}
/// <summary>
- /// Pause the recording.
+ /// Pauses recording.
/// </summary>
/// <remarks>
- /// Recording can be resumed with <see cref="Start"/>.
+ /// Recording can be resumed with <see cref="Start"/>.\n
+ /// \n
+ /// The recorder state must be <see cref="RecorderState.Recording"/> state by <see cref="Start"/> \n
+ /// \n
+ /// It has no effect if the recorder is already in the <see cref="RecorderState.Paused"/> state.
/// </remarks>
- /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
+ /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
/// <seealso cref="Start"/>
/// <seealso cref="Commit"/>
/// <seealso cref="Cancel"/>
public void Pause()
{
- int ret = Native.Pause(_handle);
- if (ret != (int)StreamRecorderError.None)
+ if (State == RecorderState.Paused)
{
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to pause the stream recorder");
+ return;
}
+
+ ValidateState(RecorderState.Recording);
+
+ Native.Pause(Handle).ThrowIfError("Failed to pause the stream recorder.");
}
/// <summary>
/// Stops recording and saves the result.
/// </summary>
/// <remarks>
- /// The recorder state must be <see cref="StreamRecorderState.Recording"/> state by <see cref="Start"/> or
- /// <see cref="StreamRecorderState.Paused"/> state by <see cref="Pause"/>
- /// When you want to record audio or video file, you need to add privilege according to rules below additionally.
+ /// The recorder state must be <see cref="RecorderState.Recording"/> state by <see cref="Start"/> or
+ /// <see cref="RecorderState.Paused"/> state by <see cref="Pause"/>.\n
+ /// \n
+ /// The recorder state will be <see cref="RecorderState.Ready"/> after commit.\n
/// <para>
- /// 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.
+ /// http://tizen.org/privilege/mediastorage is needed if the save path are relevant to media storage.
+ /// http://tizen.org/privilege/externalstorage is needed if the save path are relevant to external storage.
/// </para>
/// </remarks>
- /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
- /// <exception cref="UnauthorizedAccessException">The access ot the resources can not be granted.</exception>
+ /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
+ /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
+ /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+ /// <exception cref="UnauthorizedAccessException">The access to the resources can not be granted.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
/// <seealso cref="Start"/>
/// <seealso cref="Pause"/>
public void Commit()
{
- int ret = Native.Commit(_handle);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to save the recorded content");
- }
+ ValidateState(RecorderState.Paused, RecorderState.Recording);
+
+ Native.Commit(Handle).ThrowIfError("Failed to commit.");
}
/// <summary>
- /// Cancels the recording.
- /// The recording data is discarded and not written in the recording file.
+ /// Cancels recording.
+ /// The recording data is discarded and not written.
/// </summary>
+ /// <remarks>
+ /// The recorder state must be <see cref="RecorderState.Recording"/> state by <see cref="Start"/> or
+ /// <see cref="RecorderState.Paused"/> state by <see cref="Pause"/>.
+ /// </remarks>
+ /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
/// <seealso cref="Start"/>
/// <seealso cref="Pause"/>
public void Cancel()
{
- int ret = Native.Cancel(_handle);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to cancel the recording");
- }
- }
-
- /// <summary>
- /// Push stream buffer as recording raw data.
- /// </summary>
- public void PushBuffer(MediaPacket packet)
- {
- IntPtr _packet_h = packet.GetHandle();
+ ValidateState(RecorderState.Paused, RecorderState.Recording);
- Log.Info("Tizen.Multimedia.StreamRecorder", "PUSH stream buffer");
- int ret = Native.PushStreamBuffer(_handle, _packet_h);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to push buffer");
- }
- Log.Info("Tizen.Multimedia.StreamRecorder", "PUSH stream buffer END");
+ Native.Cancel(Handle).ThrowIfError("Failed to cancel recording.");
}
- /// <summary>
- /// Set the source type of pushed data.
- /// </summary>
- public void EnableSourceBuffer(StreamRecorderSourceType type)
+ private static bool AreVideoTypesMatched(StreamRecorderVideoFormat videoFormat, MediaFormatVideoMimeType mimeType)
{
- int ret = Native.EnableSourceBuffer(_handle, (int)type);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Failed to set EnableSourceBuffer");
- }
+ return (videoFormat == StreamRecorderVideoFormat.Nv12 && mimeType == MediaFormatVideoMimeType.NV12) ||
+ (videoFormat == StreamRecorderVideoFormat.Nv21 && mimeType == MediaFormatVideoMimeType.NV21) ||
+ (videoFormat == StreamRecorderVideoFormat.I420 && mimeType == MediaFormatVideoMimeType.I420);
}
/// <summary>
- /// Release any unmanaged resources used by this object.
+ /// Pushes a packet as recording raw data.
/// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
+ /// <param name="packet">An audio or video packet to record.</param>
+ /// <remarks>
+ /// The recorder state must be <see cref="RecorderState.Recording"/> state by <see cref="Start"/>.
+ /// </remarks>
+ /// <exception cref="InvalidOperationException">
+ /// The recorder is not in the valid state.\n
+ /// -or-\n
+ /// <paramref name="packet"/> is an audio packet but audio recording is not enabled(See <see cref="StreamRecorderOptions.Audio"/>).\n
+ /// -or-\n
+ /// <paramref name="packet"/> is a video packet but video recording is not enabled(See <see cref="StreamRecorderOptions.Video"/>).\n
+ /// -or-\n
+ /// <paramref name="packet"/> is a video packet but the <see cref="VideoMediaFormat.MimeType"/> does not match the video source format.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="StreamRecorder"/> has already been disposed.</exception>
+ /// <see cref="Prepare(StreamRecorderOptions)"/>
+ /// <seealso cref="StreamRecorderOptions.Audio"/>
+ /// <seealso cref="StreamRecorderOptions.Video"/>
+ /// <seealso cref="StreamRecorderVideoOptions.SourceFormat"/>
+ public void PushBuffer(MediaPacket packet)
{
- if (!_disposed)
+ if (packet == null)
{
- if (disposing)
- {
- // to be used if there are any other disposable objects
- }
- if (_handle != IntPtr.Zero)
- {
- Native.Destroy(_handle);
- _handle = IntPtr.Zero;
- }
- _disposed = true;
+ throw new ArgumentNullException(nameof(packet));
}
- }
- private void RegisterStreamRecorderNotifiedEvent()
- {
- _notifiedCallback = (StreamRecorderState previous, StreamRecorderState current, StreamRecorderNotify notify, IntPtr userData) =>
- {
- StreamRecorderNotifiedEventArgs eventArgs = new StreamRecorderNotifiedEventArgs(previous, current, notify);
- _recorderNotified?.Invoke(this, eventArgs);
- };
- int ret = Native.SetNotifiedCallback(_handle, _notifiedCallback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Setting notify callback failed");
- }
- }
+ ValidateState(RecorderState.Recording);
- private void UnregisterStreamRecorderNotifiedEvent()
- {
- int ret = Native.UnsetNotifiedCallback(_handle);
- if (ret != (int)StreamRecorderError.None)
+ switch (packet.Format.Type)
{
- StreamRecorderErrorFactory.ThrowException(ret, "Unsetting notify callback failed");
- }
- }
+ case MediaFormatType.Audio:
+ if (_audioEnabled == false)
+ {
+ throw new InvalidOperationException("Audio option is not set.");
+ }
+ break;
- private void RegisterBufferComsumedEvent()
- {
- _bufferConsumedCallback = (IntPtr buffer, IntPtr userData) =>
- {
- StreamRecordingBufferConsumedEventArgs eventArgs = new StreamRecordingBufferConsumedEventArgs(buffer);
- _bufferConsumed?.Invoke(this, eventArgs);
- };
- int ret = Native.SetBufferConsumedCallback(_handle, _bufferConsumedCallback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Setting buffer consumed callback failed");
- }
- }
+ case MediaFormatType.Video:
+ if (_videoEnabled == false)
+ {
+ throw new InvalidOperationException("Video option is not set.");
+ }
- private void UnregisterBufferComsumedEvent()
- {
- int ret = Native.UnsetBufferConsumedCallback(_handle);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Unsetting buffer consumed callback failed");
- }
- }
+ if (AreVideoTypesMatched(_sourceFormat, (packet.Format as VideoMediaFormat).MimeType) == false)
+ {
+ throw new InvalidOperationException("Video format does not match.");
+ }
- private void RegisterRecordingStatusChangedEvent()
- {
- _recordingStatusCallback = (ulong elapsedTime, ulong fileSize, IntPtr userData) =>
- {
- RecordingStatusChangedEventArgs eventArgs = new RecordingStatusChangedEventArgs((long)elapsedTime, (long)fileSize);
- _recordingStatusChanged?.Invoke(this, eventArgs);
- };
- int ret = Native.SetStatusChangedCallback(_handle, _recordingStatusCallback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Setting status changed callback failed");
- }
- }
+ break;
- private void UnregisterRecordingStatusChangedEvent()
- {
- int ret = Native.UnsetStatusChangedCallback(_handle);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Unsetting status changed callback failed");
+ default:
+ throw new ArgumentException("Packet is not valid.");
}
- }
- private void RegisterRecordingLimitReachedEvent()
- {
- _recordingLimitReachedCallback = (StreamRecordingLimitType type, IntPtr userData) =>
- {
- StreamRecordingLimitReachedEventArgs eventArgs = new StreamRecordingLimitReachedEventArgs(type);
- _recordingLimitReached?.Invoke(this, eventArgs);
- };
- int ret = Native.SetLimitReachedCallback(_handle, _recordingLimitReachedCallback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Setting limit reached callback failed");
- }
+ Native.PushStreamBuffer(Handle, MediaPacket.Lock.Get(packet).GetHandle())
+ .ThrowIfError("Failed to push buffer.");
}
- private void UnregisterRecordingLimitReachedEvent()
- {
- int ret = Native.UnsetLimitReachedCallback(_handle);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Unsetting limit reached callback failed");
- }
- }
+ #endregion
- private void RegisterRecordingErrorOccurredEvent()
+ #region Dispose support
+ /// <summary>
+ /// Release any unmanaged resources used by this object.
+ /// </summary>
+ public void Dispose()
{
- _recorderErrorCallback = (StreamRecorderErrorCode error, StreamRecorderState current, IntPtr userData) =>
- {
- StreamRecordingErrorOccurredEventArgs eventArgs = new StreamRecordingErrorOccurredEventArgs(error, current);
- _recordingErrorOccurred?.Invoke(this, eventArgs);
- };
- int ret = Native.SetErrorCallback(_handle, _recorderErrorCallback, IntPtr.Zero);
- if (ret != (int)StreamRecorderError.None)
- {
- StreamRecorderErrorFactory.ThrowException(ret, "Setting Error callback failed");
- }
+ Dispose(true);
}
- private void UnregisterRecordingErrorOccurredEvent()
+ /// <summary>
+ /// Releases the resources used by the StreamRecorder.
+ /// </summary>
+ /// <param name="disposing">
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ /// </param>
+ protected virtual void Dispose(bool disposing)
{
- int ret = Native.UnsetErrorCallback(_handle);
- if (ret != (int)StreamRecorderError.None)
+ if (!_disposed)
{
- StreamRecorderErrorFactory.ThrowException(ret, "Unsetting Error callback failed");
+ _handle?.Dispose();
+
+ _disposed = true;
}
}
+ #endregion
}
}
--- /dev/null
+/*
+ * 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 Native = Interop.StreamRecorder;
+
+namespace Tizen.Multimedia
+{
+ /// <summary>
+ /// Specifies the options associated with audio recording.
+ /// </summary>
+ /// <seealso cref="StreamRecorder"/>
+ /// <seealso cref="StreamRecorderOptions"/>
+ /// <seealso cref="StreamRecorderVideoOptions"/>
+ public class StreamRecorderAudioOptions
+ {
+ private const int DefaultSampleRate = 0;
+ private const int DefaultBitRate = 128000;
+ private const int DefaultChannels = 2;
+
+ /// <summary>
+ /// Initialize a new instance of the <see cref="StreamRecorderAudioOptions"/> class with the specified codec.
+ /// </summary>
+ /// <param name="codec">The <see cref="RecorderAudioCodec"/> for encoding audio stream.</param>
+ /// <remarks>
+ /// <see cref="SampleRate"/>, <see cref="BitRate"/> and <see cref="Channels"/> will be set as default.
+ /// </remarks>
+ /// <exception cref="ArgumentException"><paramref name="codec"/> is not valid.</exception>
+ public StreamRecorderAudioOptions(RecorderAudioCodec codec) :
+ this(codec, DefaultSampleRate, DefaultBitRate, DefaultChannels)
+ {
+ }
+
+ /// <summary>
+ /// Initialize a new instance of the <see cref="StreamRecorderAudioOptions"/> class with the specified
+ /// codec, sample rate, bit rate and channel value.
+ /// </summary>
+ /// <param name="codec">The <see cref="RecorderAudioCodec"/> for encoding audio stream.</param>
+ /// <param name="sampleRate">The sample rate for encoding audio stream.</param>
+ /// <param name="bitRate">The bit rate for encoding audio stream.</param>
+ /// <param name="channels">The number of channels for encoding audio stream.</param>
+ /// <exception cref="ArgumentException"><paramref name="codec"/> is not valid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="sampleRate"/> is less than zero.\n
+ /// -or-\n
+ /// <paramref name="bitRate"/> is less than or equal to zero.\n
+ /// -or-\n
+ /// <paramref name="channels"/> is less than or equal to zero.
+ /// </exception>
+ public StreamRecorderAudioOptions(RecorderAudioCodec codec, int sampleRate, int bitRate, int channels)
+ {
+ Codec = codec;
+ SampleRate = sampleRate;
+ BitRate = bitRate;
+ Channels = channels;
+ }
+
+ private RecorderAudioCodec _codec;
+
+ /// <summary>
+ /// Gets or sets the audio codec for encoding an audio stream.
+ /// </summary>
+ /// <value>The codec for audio stream recording.</value>
+ /// <exception cref="ArgumentException"><paramref name="value"/> is not valid.</exception>
+ /// <seealso cref="StreamRecorder.GetSupportedAudioCodecs"/>
+ public RecorderAudioCodec Codec
+ {
+ get => _codec;
+ set
+ {
+ ValidationUtil.ValidateEnum(typeof(RecorderAudioCodec), value, nameof(value));
+
+ _codec = value;
+ }
+ }
+
+ private int _sampleRate;
+
+ /// <summary>
+ /// Gets or sets the sampling rate of the audio stream in hertz.
+ /// </summary>
+ /// <remarks>If the value is zero, the sample rate will be decided based on input buffers.</remarks>
+ /// <value>The sample rate value for stream recorder. The default is zero.</value>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+ public int SampleRate
+ {
+ get => _sampleRate;
+ set
+ {
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Sample rate can't be less than or equal to zero.");
+ }
+
+ _sampleRate = value;
+ }
+ }
+
+ private int _bitRate;
+
+ /// <summary>
+ /// Gets or sets the bit rate of the audio encoder in bits per second.
+ /// </summary>
+ /// <value>The bit rate value for audio stream recording. The default is 128000.</value>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
+ public int BitRate
+ {
+ get => _bitRate;
+ set
+ {
+ if (value <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Bit rate can't be less than or equal to zero.");
+ }
+
+ _bitRate = value;
+ }
+ }
+
+ private int _channels;
+
+ /// <summary>
+ /// Gets or sets the number of audio channels.
+ /// </summary>
+ /// <value>The number of audio channels for audio stream recording. The default is 2.</value>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
+ public int Channels
+ {
+ get => _channels;
+ set
+ {
+ if (value <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Channels can't be less than or equal to zero.");
+ }
+
+ _channels = value;
+ }
+ }
+
+ internal void Apply(StreamRecorder recorder)
+ {
+ recorder.ValidateAudioCodec(Codec);
+
+ Native.SetAudioEncoder(recorder.Handle, Codec.ToStreamRecorderEnum()).
+ ThrowIfError("Failed to set audio codec.");
+
+ Native.SetAudioSampleRate(recorder.Handle, SampleRate).
+ ThrowIfError("Failed to set audio sample rate.");
+
+ Native.SetAudioEncoderBitrate(recorder.Handle, BitRate).
+ ThrowIfError("Failed to set audio bit rate.");
+
+ Native.SetAudioChannel(recorder.Handle, Channels).
+ ThrowIfError("Failed to set audio channels.");
+ }
+ }
+
+}
namespace Tizen.Multimedia
{
+
/// <summary>
- /// An extended EventArgs.
+ /// Provides data for the <see cref="StreamRecorder.BufferConsumed"/> event.
/// </summary>
- public class StreamRecordingBufferConsumedEventArgs : EventArgs
+ public class StreamRecorderBufferConsumedEventArgs : EventArgs
{
- private IntPtr _buffer = IntPtr.Zero;
-
- internal StreamRecordingBufferConsumedEventArgs(IntPtr buffer)
+ internal StreamRecorderBufferConsumedEventArgs(MediaPacket packet)
{
- _buffer = buffer;
+ Packet = packet;
}
/// <summary>
- /// Consumed buffer.
+ /// Gets the packet that has consumed.
/// </summary>
- public IntPtr Buffer {
- get {
- return _buffer;
- }
- }
+ public MediaPacket Packet { get; }
}
}
* limitations under the License.
*/
+using System;
+using System.Diagnostics;
+
namespace Tizen.Multimedia
{
+
+ /// <summary>
+ /// Specifies errors for <see cref="StreamRecorder"/>/
+ /// </summary>
+ public enum StreamRecorderError
+ {
+ /// <summary>
+ /// Internal error.
+ /// </summary>
+ InternalError = StreamRecorderErrorCode.InvalidOperation,
+ /// <summary>
+ /// Out of storage.
+ /// </summary>
+ OutOfStorage = StreamRecorderErrorCode.OutOfStorage
+ }
+
+ /// <summary>
+ /// Specifies the video source formats for <see cref="StreamRecorder"/>.
+ /// </summary>
+ public enum StreamRecorderVideoFormat
+ {
+ /// <summary>
+ /// Nv12 format.
+ /// </summary>
+ Nv12,
+ /// <summary>
+ /// Nv21 format.
+ /// </summary>
+ Nv21,
+ /// <summary>
+ /// I420 format.
+ /// </summary>
+ I420
+ }
+
+ #region Internal enums
+
/// <summary>
/// Enumeration for Audio Codec.
/// </summary>
- public enum StreamRecorderAudioCodec
+ internal enum StreamRecorderAudioCodec
{
/// <summary>
/// AMR codec.
/// <summary>
/// Enumeration for the file container format.
/// </summary>
- public enum StreamRecorderFileFormat
+ internal enum StreamRecorderFileFormat
{
/// <summary>
/// 3GP file format.
/// <summary>
/// Enumeration for the recorder notify type.
/// </summary>
- public enum StreamRecorderNotify
+ internal enum StreamRecorderNotify
{
/// <summary>
/// None.
/// </summary>
None = 0,
/// <summary>
- /// State changed noti.
+ /// State changed.
/// </summary>
StateChanged
}
/// <summary>
- /// Enumeration for the recording limit type.
- /// </summary>
- public enum StreamRecordingLimitType
- {
- /// <summary>
- /// Time limit in seconds of recording file
- /// </summary>
- Time,
- /// <summary>
- /// Size limit in KB(KiloBytes) of recording file.
- /// </summary>
- Size
- }
-
- /// <summary>
- /// Enumeration for stream recorder states.
- /// </summary>
- public enum StreamRecorderState
- {
- /// <summary>
- /// Stream recorder is not created.
- /// </summary>
- None,
- /// <summary>
- /// Stream recorder is created, but not prepared.
- /// </summary>
- Created,
- /// <summary>
- /// Stream recorder is ready to record.
- /// </summary>
- Prepared,
- /// <summary>
- /// Stream recorder is recording pushed packet.
- /// </summary>
- Recording,
- /// <summary>
- /// Stream recorder is paused.
- /// </summary>
- Paused
- }
-
- /// <summary>
/// Enumeration for video codec.
/// </summary>
- public enum StreamRecorderVideoCodec
+ internal enum StreamRecorderVideoCodec
{
/// <summary>
/// H263 codec.
/// <summary>
/// Enumeration for source type.
/// </summary>
- public enum StreamRecorderSourceType
+ internal enum StreamRecorderSourceType
{
/// <summary>
/// Video source
VideoAudio
}
- /// <summary>
- /// Enumeration for video source format.
- /// </summary>
- public enum StreamRecorderVideoSourceFormat
+ internal static class StreamRecorderEnumExtensions
{
- /// <summary>
- /// Nv12 Video source format
- /// </summary>
- Nv12,
- /// <summary>
- /// Nv21 video source format
- /// </summary>
- Nv21,
- /// <summary>
- /// I420 video source format
- /// </summary>
- I420
- }
+ internal static RecorderVideoCodec ToRecorderEnum(this StreamRecorderVideoCodec value)
+ {
+ switch (value)
+ {
+ case StreamRecorderVideoCodec.H263:
+ return RecorderVideoCodec.H263;
- /// <summary>
- /// Enumeration for stream recorder failure error.
- /// </summary>
- public enum StreamRecorderErrorCode
- {
- /// <summary>
- /// Sucessful.
- /// </summary>
- None = StreamRecorderError.None,
- /// <summary>
- /// Internal error.
- /// </summary>
- InvalidParameter = StreamRecorderError.InvalidParameter,
- /// <summary>
- /// Internal error.
- /// </summary>
- InvalidOperation = StreamRecorderError.InvalidOperation,
- /// <summary>
- /// Out of memory.
- /// </summary>
- OutOfMemory = StreamRecorderError.OutOfMemory
+ case StreamRecorderVideoCodec.Mpeg4:
+ return RecorderVideoCodec.Mpeg4;
+ }
+
+ Debug.Fail("Unknown video codec value.");
+ return 0;
+ }
+
+ internal static StreamRecorderVideoCodec ToStreamRecorderEnum(this RecorderVideoCodec value)
+ {
+ switch (value)
+ {
+ case RecorderVideoCodec.H263:
+ return StreamRecorderVideoCodec.H263;
+
+ case RecorderVideoCodec.Mpeg4:
+ return StreamRecorderVideoCodec.Mpeg4;
+ }
+
+ throw new NotSupportedException($"{value.ToString()} is not supported.");
+ }
+
+
+ internal static RecorderAudioCodec ToRecorderEnum(this StreamRecorderAudioCodec value)
+ {
+ switch (value)
+ {
+ case StreamRecorderAudioCodec.Aac:
+ return RecorderAudioCodec.Aac;
+
+ case StreamRecorderAudioCodec.Amr:
+ return RecorderAudioCodec.Amr;
+
+ case StreamRecorderAudioCodec.Pcm:
+ return RecorderAudioCodec.Pcm;
+ }
+
+ Debug.Fail("Unknown audio codec value.");
+ return 0;
+ }
+
+
+ internal static StreamRecorderAudioCodec ToStreamRecorderEnum(this RecorderAudioCodec value)
+ {
+ switch (value)
+ {
+ case RecorderAudioCodec.Aac:
+ return StreamRecorderAudioCodec.Aac;
+
+ case RecorderAudioCodec.Amr:
+ return StreamRecorderAudioCodec.Amr;
+
+ case RecorderAudioCodec.Pcm:
+ return StreamRecorderAudioCodec.Pcm;
+ }
+
+ throw new NotSupportedException($"{value.ToString()} is not supported.");
+ }
+
+
+ internal static RecorderFileFormat ToRecorderEnum(this StreamRecorderFileFormat value)
+ {
+ switch (value)
+ {
+ case StreamRecorderFileFormat.ThreeGp:
+ return RecorderFileFormat.ThreeGp;
+
+ case StreamRecorderFileFormat.Mp4:
+ return RecorderFileFormat.Mp4;
+
+ case StreamRecorderFileFormat.Amr:
+ return RecorderFileFormat.Amr;
+
+ case StreamRecorderFileFormat.Adts:
+ return RecorderFileFormat.Adts;
+
+ case StreamRecorderFileFormat.Wav:
+ return RecorderFileFormat.Wav;
+ }
+
+ Debug.Fail("Unknown file format value.");
+ return 0;
+ }
+
+
+ internal static StreamRecorderFileFormat ToStreamRecorderEnum(this RecorderFileFormat value)
+ {
+ switch (value)
+ {
+ case RecorderFileFormat.ThreeGp:
+ return StreamRecorderFileFormat.ThreeGp;
+
+ case RecorderFileFormat.Mp4:
+ return StreamRecorderFileFormat.Mp4;
+
+ case RecorderFileFormat.Amr:
+ return StreamRecorderFileFormat.Amr;
+
+ case RecorderFileFormat.Adts:
+ return StreamRecorderFileFormat.Adts;
+
+ case RecorderFileFormat.Wav:
+ return StreamRecorderFileFormat.Wav;
+ }
+
+ throw new NotSupportedException($"{value.ToString()} is not supported.");
+ }
}
+ #endregion
}
*/
using System;
+using System.IO;
using Tizen.Internals.Errors;
namespace Tizen.Multimedia
{
- internal enum StreamRecorderError
+ internal enum StreamRecorderErrorCode
{
None = ErrorCode.None,
InvalidParameter = ErrorCode.InvalidParameter,
NotSupported = ErrorCode.NotSupported,
}
- internal static class StreamRecorderErrorFactory
+ internal static class StreamRecorderErrorExtensions
{
- internal static void ThrowException(int errorCode, string errorMessage = null, string paramName = null)
+ internal static StreamRecorderErrorCode Ignore(this StreamRecorderErrorCode errorCode, StreamRecorderErrorCode ignore)
{
- StreamRecorderError err = (StreamRecorderError)errorCode;
- if (string.IsNullOrEmpty(errorMessage))
+ return (ignore == errorCode) ? StreamRecorderErrorCode.None : errorCode;
+ }
+
+ internal static void ThrowIfError(this StreamRecorderErrorCode err, string errorMessage)
+ {
+ if (err == StreamRecorderErrorCode.None)
{
- errorMessage = err.ToString();
+ return;
}
- switch ((StreamRecorderError)errorCode)
+
+ switch (err)
{
- case StreamRecorderError.InvalidParameter:
- throw new ArgumentException(errorMessage, paramName);
- case StreamRecorderError.OutOfMemory:
+ case StreamRecorderErrorCode.InvalidParameter:
+ throw new ArgumentException(errorMessage);
+
+ case StreamRecorderErrorCode.OutOfMemory:
throw new OutOfMemoryException(errorMessage);
- case StreamRecorderError.PermissionDenied:
+
+ case StreamRecorderErrorCode.PermissionDenied:
throw new UnauthorizedAccessException(errorMessage);
- case StreamRecorderError.NotSupported:
+
+ case StreamRecorderErrorCode.NotSupported:
throw new NotSupportedException(errorMessage);
- case StreamRecorderError.InvalidState:
- case StreamRecorderError.InvalidOperation:
- case StreamRecorderError.OutOfStorage:
+
+ case StreamRecorderErrorCode.InvalidState:
+ case StreamRecorderErrorCode.InvalidOperation:
throw new InvalidOperationException(errorMessage);
+
+ case StreamRecorderErrorCode.OutOfStorage:
+ throw new IOException(errorMessage);
}
}
}
namespace Tizen.Multimedia
{
/// <summary>
- /// An extended EventArgs class containing details about the recording limit.
+ /// Provides data for the <see cref="StreamRecorder.ErrorOccurred"/> event.
/// </summary>
- public class StreamRecordingLimitReachedEventArgs : EventArgs
+ public class StreamRecorderErrorOccurredEventArgs : EventArgs
{
- private StreamRecordingLimitType _type = StreamRecordingLimitType.Size;
-
- internal StreamRecordingLimitReachedEventArgs(StreamRecordingLimitType type)
+ internal StreamRecorderErrorOccurredEventArgs(StreamRecorderError error, RecorderState state)
{
- _type = type;
+ Error = error;
+ State = state;
}
/// <summary>
- /// The limitation type.
+ /// Gets the error code.
/// </summary>
- public StreamRecordingLimitType Type {
- get {
- return _type;
- }
- }
+ public StreamRecorderError Error { get; }
+
+ /// <summary>
+ /// Gets the state of the recorder.
+ /// </summary>
+ public RecorderState State { get; }
+
}
}
+++ /dev/null
-/*
- * 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;
-
-namespace Tizen.Multimedia
-{
- /// <summary>
- /// An extended Eventargs class which contains interrupted policy details, previous and current
- /// state of the recorder.
- /// </summary>
- public class StreamRecorderNotifiedEventArgs : EventArgs
- {
- private StreamRecorderState _previous = StreamRecorderState.None;
- private StreamRecorderState _current = StreamRecorderState.None;
- private StreamRecorderNotify _notify = StreamRecorderNotify.None;
-
- internal StreamRecorderNotifiedEventArgs(StreamRecorderState previous, StreamRecorderState current, StreamRecorderNotify notify)
- {
- _previous = previous;
- _current = current;
- _notify = notify;
- }
-
- /// <summary>
- /// The previous state of the stream recorder.
- /// </summary>
- public StreamRecorderState Previous {
- get {
- return _previous;
- }
- }
-
- /// <summary>
- /// The current state of the stream recorder.
- /// </summary>
- public StreamRecorderState Current {
- get {
- return _current;
- }
- }
-
- /// <summary>
- /// The notify of the event.
- /// </summary>
- public StreamRecorderNotify Notify {
- get {
- return _notify;
- }
- }
- }
-}
--- /dev/null
+/*
+ * 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 Native = Interop.StreamRecorder;
+
+namespace Tizen.Multimedia
+{
+ /// <summary>
+ /// Specifies the options associated with <see cref="StreamRecorder"/>.
+ /// </summary>
+ /// <seealso cref="StreamRecorder"/>
+ /// <seealso cref="StreamRecorder.Prepare(StreamRecorderOptions)"/>
+ /// <seealso cref="StreamRecorderAudioOptions"/>
+ /// <seealso cref="StreamRecorderVideoOptions"/>
+ public class StreamRecorderOptions
+ {
+ /// <summary>
+ /// Initialize a new instance of the <see cref="StreamRecorderOptions"/> class with the specified
+ /// save path and file format.
+ /// </summary>
+ /// <param name="savePath">The path that the recording result is saved.</param>
+ /// <param name="fileFormat">The file format of output file.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="savePath"/>is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="savePath"/>is an empty string.\n
+ /// -or-\n
+ /// <paramref name="fileFormat"/> is not valid.
+ /// </exception>
+ public StreamRecorderOptions(string savePath, RecorderFileFormat fileFormat)
+ {
+ SavePath = savePath;
+ FileFormat = fileFormat;
+ }
+
+ private string _savePath;
+
+ /// <summary>
+ /// Gets or sets the file path to record.
+ /// </summary>
+ /// <remarks>
+ /// If the same file already exists in the file system, then old file will be overwritten.
+ /// </remarks>
+ /// <exception cref="ArgumentNullException"><paramref name="value"/>is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="value"/>is an empty string.</exception>
+ public string SavePath
+ {
+ get => _savePath;
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ throw new ArgumentException("Path can't be an empty string.", nameof(value));
+ }
+
+ _savePath = value;
+ }
+ }
+
+ private RecorderFileFormat _fileFormat;
+
+ /// <summary>
+ /// Gets or sets the file format for recording media stream.
+ /// </summary>
+ /// <exception cref="ArgumentException"><paramref name="value"/> is not valid.</exception>
+ /// <seealso cref="StreamRecorder.GetSupportedFileFormats"/>
+ public RecorderFileFormat FileFormat
+ {
+ get => _fileFormat;
+ set
+ {
+ ValidationUtil.ValidateEnum(typeof(RecorderFileFormat), value, nameof(value));
+
+ _fileFormat = value;
+ }
+ }
+
+ private int _timeLimit;
+
+ /// <summary>
+ /// Gets or sets the time limit of recording.
+ /// </summary>
+ /// <value>
+ /// The maximum time of recording in seconds, or 0 for unlimited time.
+ /// </value>
+ /// <remarks>
+ /// After reaching the limitation, the data which is being recorded will
+ /// be discarded and not written to the file.
+ /// The recorder state must be <see cref="RecorderState.Idle"/> state.
+ /// </remarks>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+ /// <seealso cref="StreamRecorder.RecordingLimitReached"/>
+ /// <seealso cref="SizeLimit"/>
+ public int TimeLimit
+ {
+ get => _timeLimit;
+ set
+ {
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Time limit can't be less than zero.");
+ }
+
+ _timeLimit = value;
+ }
+ }
+
+ private int _sizeLimit;
+
+ /// <summary>
+ /// Gets or sets the maximum size of a recording file.
+ /// </summary>
+ /// <value>
+ /// The maximum size of a recording file in kilobytes, or 0 for unlimited size.
+ /// </value>
+ /// <remarks>
+ /// After reaching the limitation, the data which is being recorded will
+ /// be discarded and not written to the file.
+ /// </remarks>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+ /// <seealso cref="StreamRecorder.RecordingLimitReached"/>
+ /// <seealso cref="TimeLimit"/>
+ public int SizeLimit
+ {
+ get => _sizeLimit;
+ set
+ {
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Size limit can't be less than zero.");
+ }
+
+ _sizeLimit = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the options for audio recording.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="Audio"/> or <see cref="Video"/> must be set for recording.
+ /// </remarks>
+ /// <seealso cref="Video"/>
+ public StreamRecorderAudioOptions Audio { get; set; }
+
+ /// <summary>
+ /// Gets or sets the options for video recording.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="Audio"/> or <see cref="Video"/> must be set for recording.
+ /// </remarks>
+ /// <seealso cref="Audio"/>
+ public StreamRecorderVideoOptions Video { get; set; }
+
+ private StreamRecorderSourceType GetSourceType()
+ {
+ Debug.Assert(Audio != null || Video != null);
+
+ if (Audio != null && Video != null)
+ {
+ return StreamRecorderSourceType.VideoAudio;
+ }
+
+ return Audio != null ? StreamRecorderSourceType.Audio : StreamRecorderSourceType.Video;
+ }
+
+ internal void Apply(StreamRecorder recorder)
+ {
+ if (Audio == null && Video == null)
+ {
+ throw new ArgumentException("Both Audio and Video are not set.");
+ }
+
+ Native.EnableSourceBuffer(recorder.Handle, GetSourceType()).ThrowIfError("Failed to apply options.");
+
+ Native.SetFileName(recorder.Handle, SavePath).ThrowIfError("Failed to set save path.");
+
+ recorder.ValidateFileFormat(FileFormat);
+ Native.SetFileFormat(recorder.Handle, FileFormat.ToStreamRecorderEnum())
+ .ThrowIfError("Failed to set file format.");
+
+ Native.SetRecordingLimit(recorder.Handle, RecordingLimitType.Size, SizeLimit).
+ ThrowIfError("Failed to set size limit.");
+
+ Native.SetRecordingLimit(recorder.Handle, RecordingLimitType.Time, TimeLimit).
+ ThrowIfError("Failed to set time limit.");
+
+ Audio?.Apply(recorder);
+
+ Video?.Apply(recorder);
+ }
+ }
+}
namespace Tizen.Multimedia
{
/// <summary>
- /// An extended EventArgs class which contains details about error status and
- /// state of the recorder when it failed.
+ /// Provides data for the <see cref="StreamRecorder.StateChanged"/> event.
/// </summary>
- public class StreamRecordingErrorOccurredEventArgs : EventArgs
+ public class StreamRecorderStateChangedEventArgs : EventArgs
{
- private StreamRecorderErrorCode _error = StreamRecorderErrorCode.InvalidOperation;
- private StreamRecorderState _state = StreamRecorderState.None;
-
- internal StreamRecordingErrorOccurredEventArgs(StreamRecorderErrorCode error, StreamRecorderState state)
+ internal StreamRecorderStateChangedEventArgs(RecorderState previous, RecorderState current)
{
- _error = error;
- _state = state;
+ Previous = previous;
+ Current = current;
}
/// <summary>
- /// The error code.
+ /// Gets the previous state of the stream recorder.
/// </summary>
- public StreamRecorderErrorCode Error {
- get {
- return _error;
- }
- }
+ public RecorderState Previous { get; }
/// <summary>
- /// The state of the recorder.
+ /// Gets the current state of the stream recorder.
/// </summary>
- public StreamRecorderState State {
- get {
- return _state;
- }
- }
-
+ public RecorderState Current { get; }
}
}
--- /dev/null
+/*
+ * 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 Native = Interop.StreamRecorder;
+
+namespace Tizen.Multimedia
+{
+ /// <summary>
+ /// Specifies the options associated with video recording.
+ /// </summary>
+ /// <seealso cref="StreamRecorder"/>
+ /// <seealso cref="StreamRecorderOptions"/>
+ /// <seealso cref="StreamRecorderAudioOptions"/>
+ public class StreamRecorderVideoOptions
+ {
+ private const int DefaultBitRate = 0;
+
+ /// <summary>
+ /// Initialize a new instance of the <see cref="StreamRecorderVideoOptions"/> class with the specified
+ /// codec, resolution, source format and frame rate.
+ /// </summary>
+ /// <param name="codec">The <see cref="RecorderVideoCodec"/> for encoding video stream.</param>
+ /// <param name="resolution">The resolution of video recording.</param>
+ /// <param name="sourceFormat">The format of source stream.</param>
+ /// <param name="frameRate">The frame rate for encoding video stream.</param>
+ /// <remarks>
+ /// <see cref="BitRate"/> will be set as default.
+ /// </remarks>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="codec"/> is not valid.\n
+ /// -or-\n
+ /// <paramref name="sourceFormat"/> is not valid.\n
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Width or height of <paramref name="resolution"/> is less than or equal to zero.\n
+ /// -or-\n
+ /// <paramref name="frameRate"/> is less than or equal to zero.\n
+ /// </exception>
+ public StreamRecorderVideoOptions(RecorderVideoCodec codec, Size resolution,
+ StreamRecorderVideoFormat sourceFormat, int frameRate) :
+ this(codec, resolution, sourceFormat, frameRate, DefaultBitRate)
+ {
+ }
+
+ /// <summary>
+ /// Initialize a new instance of the <see cref="StreamRecorderVideoOptions"/> class with the specified
+ /// codec, resolution, source format, frame rate and bit rate.
+ /// </summary>
+ /// <param name="codec">The <see cref="RecorderVideoCodec"/> for encoding video stream.</param>
+ /// <param name="resolution">The resolution of video recording.</param>
+ /// <param name="sourceFormat">The format of source stream.</param>
+ /// <param name="frameRate">The frame rate for encoding video stream.</param>
+ /// <param name="bitRate">The bit rate for encoding video stream.</param>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="codec"/> is not valid.\n
+ /// -or-\n
+ /// <paramref name="sourceFormat"/> is not valid.\n
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Width or height of <paramref name="resolution"/> is less than or equal to zero.\n
+ /// -or-\n
+ /// <paramref name="frameRate"/> is less than or equal to zero.\n
+ /// -or-\n
+ /// <paramref name="bitRate"/> is less than zero.
+ /// </exception>
+ public StreamRecorderVideoOptions(RecorderVideoCodec codec, Size resolution,
+ StreamRecorderVideoFormat sourceFormat, int frameRate, int bitRate)
+ {
+ Codec = codec;
+ Resolution = resolution;
+ SourceFormat = sourceFormat;
+ FrameRate = frameRate;
+ BitRate = bitRate;
+ }
+
+ private RecorderVideoCodec _codec;
+
+ /// <summary>
+ /// Gets or sets the video codec for encoding video stream.
+ /// </summary>
+ /// <value>The codec for video stream recording.</value>
+ /// <exception cref="ArgumentException"><paramref name="value"/> is not valid.</exception>
+ /// <seealso cref="StreamRecorder.GetSupportedVideoCodecs"/>
+ public RecorderVideoCodec Codec
+ {
+ get => _codec;
+ set
+ {
+ ValidationUtil.ValidateEnum(typeof(RecorderVideoCodec), value, nameof(value));
+
+ _codec = value;
+ }
+ }
+
+ private Size _resolution;
+
+ /// <summary>
+ /// Gets or sets the resolution of the video recording.
+ /// </summary>
+ /// <value>The output resolution for video stream recording.</value>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Width or height of <paramref name="value"/> is less than or equal to zero.
+ /// </exception>
+ /// <seealso cref="StreamRecorder.GetSupportedVideoResolutions"/>
+ public Size Resolution
+ {
+ get => _resolution;
+ set
+ {
+ if (value.Width <= 0 || value.Height <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Resolution can't be less than or equal to zero.");
+ }
+
+ _resolution = value;
+ }
+ }
+
+ private int _frameRate;
+
+ /// <summary>
+ /// Gets or sets the frame rate for recording media stream.
+ /// </summary>
+ /// <value>The frame rate value for video stream recording.</value>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
+ public int FrameRate
+ {
+ get => _frameRate;
+ set
+ {
+ if (value <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Frame rate can't be less than or equal to zero.");
+ }
+ _frameRate = value;
+ }
+ }
+
+ private StreamRecorderVideoFormat _sourceFormat;
+
+ /// <summary>
+ /// Gets or sets the video source format for recording media stream.
+ /// </summary>
+ /// <value>The source format of buffers for video stream recording.</value>
+ /// <exception cref="ArgumentException"><paramref name="value"/> is not valid.</exception>
+ public StreamRecorderVideoFormat SourceFormat
+ {
+ get => _sourceFormat;
+ set
+ {
+ ValidationUtil.ValidateEnum(typeof(StreamRecorderVideoFormat), value, nameof(value));
+
+ _sourceFormat = value;
+ }
+ }
+
+ private int _bitRate;
+
+ /// <summary>
+ /// The bit rate of the video encoder in bits per second.
+ /// </summary>
+ /// <value>The bit rate value for video stream recording. The default is 0.</value>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception>
+ public int BitRate
+ {
+ get => _bitRate;
+ set
+ {
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), value,
+ "Bit rate can't be less than or equal to zero.");
+ }
+ _bitRate = value;
+ }
+ }
+
+ internal void Apply(StreamRecorder recorder)
+ {
+ recorder.ValidateVideoCodec(Codec);
+
+ Native.SetVideoEncoder(recorder.Handle, Codec.ToStreamRecorderEnum()).
+ ThrowIfError("Failed to set video codec.");
+
+ recorder.ValidateVideoResolution(Resolution);
+
+ Native.SetVideoResolution(recorder.Handle, Resolution.Width, Resolution.Height).
+ ThrowIfError("Failed to set video resolution.");
+
+ Native.SetVideoFrameRate(recorder.Handle, FrameRate).
+ ThrowIfError("Failed to set video frame rate.");
+
+ Native.SetVideoEncoderBitRate(recorder.Handle, BitRate).
+ ThrowIfError("Failed to set video bit rate.");
+
+ Native.SetVideoSourceFormat(recorder.Handle, SourceFormat).
+ ThrowIfError("Failed to set video source format.");
+ }
+ }
+
+}
+++ /dev/null
-/*
- * 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 Native = Interop.StreamRecorder;
-
-namespace Tizen.Multimedia
-{
- /// <summary>
- /// Resolution for stream recorder.
- /// </summary>
- public class StreamRecorderVideoResolution
- {
- private int _width, _height;
- private bool _interopFlag;
- internal IntPtr _Handle;
-
- internal StreamRecorderVideoResolution(IntPtr handle)
- {
- _Handle = handle;
- _interopFlag = true;
- int ret = Native.GetVideoResolution(_Handle, out _width, out _height);
- StreamRecorderError err = (StreamRecorderError)ret;
- Log.Info(StreamRecorderLog.Tag, "width " + _width + " height " + _height + "return " + err.ToString());
- }
-
- internal StreamRecorderVideoResolution(int width, int height)
- {
- _interopFlag = false;
- _width = width;
- _height = height;
- }
-
- /// <summary>
- /// The video width.
- /// </summary>
- /// <value>The width.</value>
- public int Width {
- get {
- if(_interopFlag == true)
- Native.GetVideoResolution(_Handle, out _width, out _height);
- return _width;
- }
- set {
- _width = value;
- if(_interopFlag == true) {
- int ret = Native.SetVideoResolution(_Handle, _width, _height);
- StreamRecorderError err = (StreamRecorderError)ret;
- Log.Info(StreamRecorderLog.Tag, " set width " + _width + " height " + _height + "set return " + err.ToString());
- }
- }
- }
-
- /// <summary>
- /// The video height.
- /// </summary>
- /// <value>The height.</value>
- public int Height {
- get {
- if(_interopFlag == true)
- Native.GetVideoResolution(_Handle, out _width, out _height);
- return _height;
- }
- set {
- _height = value;
- if(_interopFlag == true) {
- int ret = Native.SetVideoResolution(_Handle, _width, _height);
- StreamRecorderError err = (StreamRecorderError)ret;
- Log.Info(StreamRecorderLog.Tag, " set width " + _width + " height " + _height + "set return " + err.ToString());
- }
- }
- }
- }
-}