/*
* 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.Runtime.InteropServices;
using Tizen.Internals.Errors;
using Native = Interop.StreamRecorder;
namespace Tizen.Multimedia
{
static internal class StreamRecorderLog
{
internal const string Tag = "Tizen.Multimedia.StreamRecorder";
}
///
/// Provides methods to control stream recorder.
///
///
/// StreamRecorder class provides functions to record raw image frame
/// also provides recording start, stop and save the content etc.
///
public class StreamRecorder : IDisposable
{
private IntPtr _handle;
private bool _disposed = false;
///
/// Occurred when recording is progressing for recording status.
///
private EventHandler _recordingStatusChanged;
private Native.RecordingStatusCallback _recordingStatusCallback;
///
/// Occurred when recording time or size reach limit.
///
private EventHandler _recordingLimitReached;
private Native.RecordingLimitReachedCallback _recordingLimitReachedCallback;
///
/// Occurred when streamrecorder complete to use pushed buffer.
///
private EventHandler _bufferConsumed;
private Native.BufferConsumedCallback _bufferConsumedCallback;
///
/// Occurred when streamrecorder state is changed.
///
private EventHandler _recorderNotified;
private Native.NotifiedCallback _notifiedCallback;
///
/// Occurred when error is occured.
///
private EventHandler _recordingErrorOccurred;
private Native.RecorderErrorCallback _recorderErrorCallback;
private List _formats;
private List _audioCodec;
private List _videoCodec;
private List _resolutions;
StreamRecorderVideoResolution _videoResolution = null;
///
/// Stream recorder constructor.
///
public StreamRecorder()
{
int ret = Native.Create(out _handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to create stream recorder");
}
_formats = new List();
_audioCodec = new List();
_videoCodec = new List();
_resolutions = new List();
_videoResolution = new StreamRecorderVideoResolution(_handle);
}
///
/// Stream recorder destructor.
///
~StreamRecorder()
{
Dispose(false);
}
///
/// Event that occurs when streamrecorder state is changed.
///
public event EventHandler RecorderNotified
{
add
{
if (_recorderNotified == null)
{
RegisterStreamRecorderNotifiedEvent();
}
_recorderNotified += value;
}
remove
{
_recorderNotified -= value;
if (_recorderNotified == null)
{
UnregisterStreamRecorderNotifiedEvent();
}
}
}
///
/// Event that occurs when buffer had comsumed completely.
///
public event EventHandler BufferConsumed
{
add
{
if (_bufferConsumed == null)
{
RegisterBufferComsumedEvent();
}
_bufferConsumed += value;
}
remove
{
_bufferConsumed -= value;
if (_bufferConsumed == null)
{
UnregisterBufferComsumedEvent();
}
}
}
///
/// Event that occurs when recording status changed.
///
public event EventHandler RecordingStatusChanged
{
add
{
if (_recordingStatusChanged == null)
{
RegisterRecordingStatusChangedEvent();
}
_recordingStatusChanged += value;
}
remove
{
_recordingStatusChanged -= value;
if (_recordingStatusChanged == null)
{
UnregisterRecordingStatusChangedEvent();
}
}
}
///
/// Event that occurs when recording limit is reached.
///
public event EventHandler RecordingLimitReached
{
add
{
if (_recordingLimitReached == null)
{
RegisterRecordingLimitReachedEvent();
}
_recordingLimitReached += value;
}
remove
{
_recordingLimitReached -= value;
if (_recordingLimitReached == null)
{
UnregisterRecordingLimitReachedEvent();
}
}
}
///
/// Event that occurs when an error occured during recorder operation.
///
public event EventHandler RecordingErrorOccurred
{
add
{
if (_recordingErrorOccurred == null)
{
RegisterRecordingErrorOccurredEvent();
}
_recordingErrorOccurred += value;
}
remove
{
_recordingErrorOccurred -= value;
if (_recordingErrorOccurred == null)
{
UnregisterRecordingErrorOccurredEvent();
}
}
}
///
/// The file path to record.
///
///
/// If the same file already exists in the file system, then old file
/// will be overwritten.
///
public string FilePath
{
get
{
IntPtr val;
int ret = Native.GetFileName(_handle, out val);
if ((StreamRecorderError)ret != StreamRecorderError.None)
{
Log.Error(StreamRecorderLog.Tag, "Failed to get filepath, " + (StreamRecorderError)ret);
}
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");
}
}
}
///
/// Get the current state of the stream recorder.
///
/// 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;
}
}
///
/// Get/Set the file format for recording media stream.
///
///
/// Must set .
/// The recorder state must be state.
///
/// The format does not valid.
///
public StreamRecorderFileFormat FileFormat
{
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);
}
}
}
///
/// The audio codec for encoding an audio stream.
///
///
/// Must set or
/// by
///
/// The codec does not valid.
///
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);
}
}
}
///
/// The video codec for encoding video stream.
///
///
/// Must set or
/// by
///
/// The codec does not valid.
///
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);
}
}
}
///
/// The maximum size of a recording file in KB(kilobytes). If 0, means
/// unlimited recording size.
///
///
/// After reaching the limitation, the data which is being recorded will
/// be discarded and not written to the file.
/// The recorder state must be state.
///
/// The value set to below 0.
///
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");
}
}
}
///
/// The time limit of a recording file in Seconds. If 0, means unlimited recording
/// time.
///
///
/// After reaching the limitation, the data which is being recorded will
/// be discarded and not written to the file.
/// The recorder state must be state.
///
/// The value set to below 0.
///
public int TimeLimit
{
get
{
int val = 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
{
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");
}
}
}
///
/// The sampling rate of an audio stream in hertz.
///
///
/// The recorder state must be state.
/// Must set or
/// by .
///
/// The value set to below 0.
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");
}
}
}
///
/// The bitrate of an audio encoder in bits per second.
///
///
/// The recorder state must be state.
/// Must set or
/// by
///
/// The value set to below 0.
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");
}
}
}
///
/// The bitrate of an video encoder in bits per second.
///
///
/// The recorder state must be state.
/// Must set or
/// by
///
/// The value set to below 0.
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");
}
}
}
///
/// The video frame rate for recording media stream.
///
///
/// The recorder state must be state.
/// Must set or
/// by
///
/// The value set to below 0.
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);
}
}
}
///
/// Get or Set the video source format for recording media stream.
///
/// The value set to a invalid value.
///
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);
}
}
}
///
/// The number of audio channel.
///
///
/// 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 state.
///
/// The value set to a invalid value.
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");
}
}
}
///
/// Video resolution of the video recording.
///
///
/// Must set or
/// by
/// The recorder state must be state.
///
/// The value set to a invalid value.
///
public StreamRecorderVideoResolution Resolution
{
get
{
return _videoResolution;
}
}
///
/// Retrieves all the file formats supported by the stream recorder.
///
///
/// It returns a list containing all the supported file
/// formats by Stream recorder.
///
///
public IEnumerable 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;
}
}
///
/// Retrieves all the audio encoders supported by the recorder.
///
///
/// It returns a list containing all the supported audio encoders
/// by recorder.
///
///
public IEnumerable 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;
}
}
///
/// Retrieves all the video encoders supported by the recorder.
///
///
/// It returns a list containing all the supported video encoders
/// by recorder.
///
///
public IEnumerable 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;
}
}
///
/// Retrieves all the video resolutions supported by the recorder.
///
///
/// It returns videoresolution list containing the width and height of
/// different resolutions supported by recorder.
///
///
public IEnumerable 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;
}
}
///
/// Prepare the stream recorder.
///
///
/// Before calling the function, it is required to set ,
/// , and properties of recorder.
///
/// The streamrecorder is not in the valid state.
///
public void Prepare()
{
int ret = Native.Prepare(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to prepare stream recorder");
}
}
///
/// Resets the stream recorder.
///
///
/// The recorder state must be state by , and .
/// The StreamRecorder state will be .
///
/// The streamrecorder is not in the valid state.
///
public void Unprepare()
{
int ret = Native.Unprepare(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to reset the stream recorder");
}
}
///
/// Starts the recording.
///
///
/// 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 state by or
/// state by .
/// The filename shuild be set by
///
/// The streamrecorder is not in the valid state.
/// The access ot the resources can not be granted.
///
///
///
///
///
public void Start()
{
int ret = Native.Start(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to start the stream recorder");
}
}
///
/// Pause the recording.
///
///
/// Recording can be resumed with .
///
/// The streamrecorder is not in the valid state.
///
///
///
public void Pause()
{
int ret = Native.Pause(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to pause the stream recorder");
}
}
///
/// Stops recording and saves the result.
///
///
/// The recorder state must be state by or
/// state by
/// When you want to record audio or video file, you need to add privilege according to rules below additionally.
///
/// 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.
///
///
/// The streamrecorder is not in the valid state.
/// The access ot the resources can not be granted.
///
///
public void Commit()
{
int ret = Native.Commit(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to save the recorded content");
}
}
///
/// Cancels the recording.
/// The recording data is discarded and not written in the recording file.
///
///
///
public void Cancel()
{
int ret = Native.Cancel(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to cancel the recording");
}
}
///
/// Push stream buffer as recording raw data.
///
public void PushBuffer(MediaPacket packet)
{
IntPtr _packet_h = packet.GetHandle();
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");
}
///
/// Set the source type of pushed data.
///
public void EnableSourceBuffer(StreamRecorderSourceType type)
{
int ret = Native.EnableSourceBuffer(_handle, (int)type);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Failed to set EnableSourceBuffer");
}
}
///
/// Release any unmanaged resources used by this object.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// to be used if there are any other disposable objects
}
if (_handle != IntPtr.Zero)
{
Native.Destroy(_handle);
_handle = IntPtr.Zero;
}
_disposed = true;
}
}
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");
}
}
private void UnregisterStreamRecorderNotifiedEvent()
{
int ret = Native.UnsetNotifiedCallback(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Unsetting notify callback failed");
}
}
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");
}
}
private void UnregisterBufferComsumedEvent()
{
int ret = Native.UnsetBufferConsumedCallback(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Unsetting buffer consumed callback failed");
}
}
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");
}
}
private void UnregisterRecordingStatusChangedEvent()
{
int ret = Native.UnsetStatusChangedCallback(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Unsetting status changed callback failed");
}
}
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");
}
}
private void UnregisterRecordingLimitReachedEvent()
{
int ret = Native.UnsetLimitReachedCallback(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Unsetting limit reached callback failed");
}
}
private void RegisterRecordingErrorOccurredEvent()
{
_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");
}
}
private void UnregisterRecordingErrorOccurredEvent()
{
int ret = Native.UnsetErrorCallback(_handle);
if (ret != (int)StreamRecorderError.None)
{
StreamRecorderErrorFactory.ThrowException(ret, "Unsetting Error callback failed");
}
}
}
}