Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.StreamRecorder / StreamRecorder / StreamRecorder.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using Tizen.Internals.Errors;
21 using Native = Interop.StreamRecorder;
22
23 namespace Tizen.Multimedia
24 {
25     static internal class StreamRecorderLog
26     {
27         internal const string Tag = "Tizen.Multimedia.StreamRecorder";
28     }
29
30     /// <summary>
31     /// Provides methods to control stream recorder.
32     /// </summary>
33     /// <remarks>
34     /// StreamRecorder class provides functions to record raw image frame
35     /// also provides recording start, stop and save the content etc.
36     /// </remarks>
37     public class StreamRecorder : IDisposable
38     {
39         private IntPtr _handle;
40         private bool _disposed = false;
41         /// <summary>
42         /// Occurred when recording is progressing for recording status.
43         /// </summary>
44         private EventHandler<RecordingProgressEventArgs> _recordingStatusChanged;
45         private Native.RecordingStatusCallback _recordingStatusCallback;
46         /// <summary>
47         /// Occurred when recording time or size reach limit.
48         /// </summary>
49         private EventHandler<StreamRecordingLimitReachedEventArgs> _recordingLimitReached;
50         private Native.RecordingLimitReachedCallback _recordingLimitReachedCallback;
51         /// <summary>
52         /// Occurred when streamrecorder complete to use pushed buffer.
53         /// </summary>
54         private EventHandler<StreamRecordingBufferConsumedEventArgs> _bufferConsumed;
55         private Native.BufferConsumedCallback _bufferConsumedCallback;
56         /// <summary>
57         /// Occurred when streamrecorder state is changed.
58         /// </summary>
59         private EventHandler<StreamRecorderNotifiedEventArgs> _recorderNotified;
60         private Native.NotifiedCallback _notifiedCallback;
61         /// <summary>
62         /// Occurred when error is occured.
63         /// </summary>
64         private EventHandler<StreamRecordingErrorOccurredEventArgs> _recordingErrorOccurred;
65         private Native.RecorderErrorCallback _recorderErrorCallback;
66
67         private List<StreamRecorderFileFormat> _formats;
68         private List<StreamRecorderAudioCodec> _audioCodec;
69         private List<StreamRecorderVideoCodec> _videoCodec;
70         private List<StreamRecorderVideoResolution> _resolutions;
71         StreamRecorderVideoResolution _videoResolution = null;
72
73         /// <summary>
74         /// Stream recorder constructor.
75         /// </summary>
76         public StreamRecorder()
77         {
78             int ret = Native.Create(out _handle);
79             if (ret != (int)StreamRecorderError.None)
80             {
81                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to create stream recorder");
82             }
83             _formats = new List<StreamRecorderFileFormat>();
84             _audioCodec = new List<StreamRecorderAudioCodec>();
85             _videoCodec = new List<StreamRecorderVideoCodec>();
86             _resolutions = new List<StreamRecorderVideoResolution>();
87             _videoResolution = new StreamRecorderVideoResolution(_handle);
88         }
89
90         /// <summary>
91         /// Stream recorder destructor.
92         /// </summary>
93         ~StreamRecorder()
94         {
95             Dispose(false);
96         }
97
98         /// <summary>
99         /// Event that occurs when streamrecorder state is changed.
100         /// </summary>
101         public event EventHandler<StreamRecorderNotifiedEventArgs> RecorderNotified
102         {
103             add
104             {
105                 if (_recorderNotified == null)
106                 {
107                     RegisterStreamRecorderNotifiedEvent();
108                 }
109                 _recorderNotified += value;
110             }
111             remove
112             {
113                 _recorderNotified -= value;
114                 if (_recorderNotified == null)
115                 {
116                     UnregisterStreamRecorderNotifiedEvent();
117                 }
118             }
119         }
120
121         /// <summary>
122         /// Event that occurs when buffer had comsumed completely.
123         /// </summary>
124         public event EventHandler<StreamRecordingBufferConsumedEventArgs> BufferConsumed
125         {
126             add
127             {
128                 if (_bufferConsumed == null)
129                 {
130                     RegisterBufferComsumedEvent();
131                 }
132                 _bufferConsumed += value;
133             }
134             remove
135             {
136                 _bufferConsumed -= value;
137                 if (_bufferConsumed == null)
138                 {
139                     UnregisterBufferComsumedEvent();
140                 }
141             }
142         }
143
144         /// <summary>
145         /// Event that occurs when recording status changed.
146         /// </summary>
147         public event EventHandler<RecordingProgressEventArgs> RecordingStatusChanged
148         {
149             add
150             {
151                 if (_recordingStatusChanged == null)
152                 {
153                     RegisterRecordingStatusChangedEvent();
154                 }
155                 _recordingStatusChanged += value;
156             }
157             remove
158             {
159                 _recordingStatusChanged -= value;
160                 if (_recordingStatusChanged == null)
161                 {
162                     UnregisterRecordingStatusChangedEvent();
163                 }
164             }
165         }
166
167         /// <summary>
168         /// Event that occurs when recording limit is reached.
169         /// </summary>
170         public event EventHandler<StreamRecordingLimitReachedEventArgs> RecordingLimitReached
171         {
172             add
173             {
174                 if (_recordingLimitReached == null)
175                 {
176                     RegisterRecordingLimitReachedEvent();
177                 }
178                 _recordingLimitReached += value;
179             }
180             remove
181             {
182                 _recordingLimitReached -= value;
183                 if (_recordingLimitReached == null)
184                 {
185                     UnregisterRecordingLimitReachedEvent();
186                 }
187             }
188         }
189
190         /// <summary>
191         /// Event that occurs when an error occured during recorder operation.
192         /// </summary>
193         public event EventHandler<StreamRecordingErrorOccurredEventArgs> RecordingErrorOccurred
194         {
195             add
196             {
197                 if (_recordingErrorOccurred == null)
198                 {
199                     RegisterRecordingErrorOccurredEvent();
200                 }
201                 _recordingErrorOccurred += value;
202             }
203             remove
204             {
205                 _recordingErrorOccurred -= value;
206                 if (_recordingErrorOccurred == null)
207                 {
208                     UnregisterRecordingErrorOccurredEvent();
209                 }
210             }
211         }
212
213         /// <summary>
214         /// The file path to record.
215         /// </summary>
216         /// <remarks>
217         /// If the same file already exists in the file system, then old file
218         /// will be overwritten.
219         /// </remarks>
220         public string FilePath
221         {
222             get
223             {
224                 IntPtr val;
225                 int ret = Native.GetFileName(_handle, out val);
226                 if ((StreamRecorderError)ret != StreamRecorderError.None)
227                 {
228                     Log.Error(StreamRecorderLog.Tag, "Failed to get filepath, " + (StreamRecorderError)ret);
229                 }
230                 string result = Marshal.PtrToStringAnsi(val);
231                 LibcSupport.Free(val);
232                 return result;
233             }
234             set
235             {
236                 int ret = Native.SetFileName(_handle, value);
237                 if ((StreamRecorderError)ret != StreamRecorderError.None)
238                 {
239                     Log.Error(StreamRecorderLog.Tag, "Failed to set filepath, " + (StreamRecorderError)ret);
240                     StreamRecorderErrorFactory.ThrowException(ret, "Failed to set filepath");
241                 }
242             }
243         }
244
245         /// <summary>
246         /// Get the current state of the stream recorder.
247         /// </summary>
248         /// <value> The current state of stream recorder.
249         public StreamRecorderState State
250         {
251             get
252             {
253                 int val = 0;
254
255                 int ret = Native.GetState(_handle, out val);
256                 if ((StreamRecorderError)ret != StreamRecorderError.None)
257                 {
258                     Log.Error(StreamRecorderLog.Tag, "Failed to get stream recorder state, " + (StreamRecorderError)ret);
259                 }
260                 return (StreamRecorderState)val;
261             }
262         }
263
264         /// <summary>
265         /// Get/Set the file format for recording media stream.
266         /// </summary>
267         /// <remarks>
268         /// Must set <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>.
269         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
270         /// </remarks>
271         /// <exception cref="ArgumentException">The format does not valid.</exception>
272         /// <seealso cref="SupportedFileFormats"/>
273         public StreamRecorderFileFormat FileFormat
274         {
275             get
276             {
277                 int val = 0;
278
279                 int ret = Native.GetFileFormat(_handle, out val);
280                 if ((StreamRecorderError)ret != StreamRecorderError.None)
281                 {
282                     Log.Error(StreamRecorderLog.Tag, "Failed to get file format, " + (StreamRecorderError)ret);
283                 }
284                 return (StreamRecorderFileFormat)val;
285             }
286             set
287             {
288                 int ret = Native.SetFileFormat(_handle, (int)value);
289                 if ((StreamRecorderError)ret != StreamRecorderError.None)
290                 {
291                     Log.Error(StreamRecorderLog.Tag, "Failed to set file format, " + (StreamRecorderError)ret);
292                     StreamRecorderErrorFactory.ThrowException(ret);
293                 }
294             }
295         }
296
297         /// <summary>
298         /// The audio codec for encoding an audio stream.
299         /// </summary>
300         /// <remarks>
301         /// Must set <see cref="StreamRecorderSourceType.Audio"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
302         /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
303         /// </remarks>
304         /// <exception cref="ArgumentException">The codec does not valid.</exception>
305         /// <seealso cref="SupportedAudioEncodings"/>
306         public StreamRecorderAudioCodec AudioCodec
307         {
308             get
309             {
310                 int val = 0;
311
312                 int ret = Native.GetAudioEncoder(_handle, out val);
313                 if ((StreamRecorderError)ret != StreamRecorderError.None)
314                 {
315                     Log.Error(StreamRecorderLog.Tag, "Failed to get audio codec, " + (StreamRecorderError)ret);
316                 }
317                 return (StreamRecorderAudioCodec)val;
318             }
319             set
320             {
321                 int ret = Native.SetAudioEncoder(_handle, (int)value);
322                 if ((StreamRecorderError)ret != StreamRecorderError.None)
323                 {
324                     Log.Error(StreamRecorderLog.Tag, "Failed to set audio codec, " + (StreamRecorderError)ret);
325                     StreamRecorderErrorFactory.ThrowException(ret);
326                 }
327             }
328         }
329
330         /// <summary>
331         /// The video codec for encoding video stream.
332         /// </summary>
333         /// <remarks>
334         /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
335         /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
336         /// </remarks>
337         /// <exception cref="ArgumentException">The codec does not valid.</exception>
338         /// <seealso cref="SupportedVideoEncodings"/>
339         public StreamRecorderVideoCodec VideoCodec
340         {
341             get
342             {
343                 int val = 0;
344
345                 int ret = Native.GetVideoEncoder(_handle, out val);
346                 if ((StreamRecorderError)ret != StreamRecorderError.None)
347                 {
348                     Log.Error(StreamRecorderLog.Tag, "Failed to get video codec, " + (StreamRecorderError)ret);
349                 }
350                 return (StreamRecorderVideoCodec)val;
351             }
352             set
353             {
354                 int ret = Native.SetVideoEncoder(_handle, (int)value);
355
356                 if ((StreamRecorderError)ret != StreamRecorderError.None)
357                 {
358                     Log.Error(StreamRecorderLog.Tag, "Failed to set video codec, " + (StreamRecorderError)ret);
359                     StreamRecorderErrorFactory.ThrowException(ret);
360                 }
361             }
362         }
363
364         /// <summary>
365         /// The maximum size of a recording file in KB(kilobytes). If 0, means
366         /// unlimited recording size.
367         /// </summary>
368         /// <remarks>
369         /// After reaching the limitation, the data which is being recorded will
370         /// be discarded and not written to the file.
371         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
372         /// </remarks>
373         /// <exception cref="ArgumentException">The value set to below 0.</exception>
374         /// <seealso cref="StreamRecordingLimitReachedEventArgs"/>
375         public int SizeLimit
376         {
377             get
378             {
379                 int val = 0;
380
381                 int ret = Native.GetRecordingLimit(_handle, 1, out val);
382                 if ((StreamRecorderError)ret != StreamRecorderError.None)
383                 {
384                     Log.Error(StreamRecorderLog.Tag, "Failed to get size limit, " + (StreamRecorderError)ret);
385                 }
386                 return val;
387             }
388             set
389             {
390                 int ret = Native.SetRecordingLimit(_handle, 1, value);
391                 if ((StreamRecorderError)ret != StreamRecorderError.None)
392                 {
393                     Log.Error(StreamRecorderLog.Tag, "Failed to set sizelimit, " + (StreamRecorderError)ret);
394                     StreamRecorderErrorFactory.ThrowException(ret, "Failed to set size limit");
395                 }
396             }
397         }
398
399         /// <summary>
400         /// The time limit of a recording file in Seconds. If 0, means unlimited recording
401         /// time.
402         /// </summary>
403         /// <remarks>
404         /// After reaching the limitation, the data which is being recorded will
405         /// be discarded and not written to the file.
406         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
407         /// </remarks>
408         /// <exception cref="ArgumentException">The value set to below 0.</exception>
409         /// <seealso cref="StreamRecordingLimitReachedEventArgs"/>
410         public int TimeLimit
411         {
412             get
413             {
414                 int val = 0;
415
416                 int ret = Native.GetRecordingLimit(_handle, 0, out val);
417                 if ((StreamRecorderError)ret != StreamRecorderError.None)
418                 {
419                     Log.Error(StreamRecorderLog.Tag, "Failed to get time limit, " + (StreamRecorderError)ret);
420                 }
421                 return val;
422             }
423             set
424             {
425                 int ret = Native.SetRecordingLimit(_handle, 0, value);
426                 if ((StreamRecorderError)ret != StreamRecorderError.None)
427                 {
428                     Log.Error(StreamRecorderLog.Tag, "Failed to set timelimit, " + (StreamRecorderError)ret);
429                     StreamRecorderErrorFactory.ThrowException(ret, "Failed to set time limit");
430                 }
431             }
432         }
433
434         /// <summary>
435         /// The sampling rate of an audio stream in hertz.
436         /// </summary>
437         /// <remarks>
438         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
439         /// Must set <see cref="StreamRecorderSourceType.Audio"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
440         /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>.
441         /// </remarks>
442         /// <exception cref="ArgumentException">The value set to below 0.</exception>
443         public int AudioSampleRate
444         {
445             get
446             {
447                 int val = 0;
448
449                 int ret = Native.GetAudioSampleRate(_handle, out val);
450                 if ((StreamRecorderError)ret != StreamRecorderError.None)
451                 {
452                     Log.Error(StreamRecorderLog.Tag, "Failed to get audio samplerate, " + (StreamRecorderError)ret);
453                 }
454                 return val;
455             }
456             set
457             {
458                 int ret = Native.SetAudioSampleRate(_handle, value);
459                 if ((StreamRecorderError)ret != StreamRecorderError.None)
460                 {
461                     Log.Error(StreamRecorderLog.Tag, "Failed to set audio samplerate, " + (StreamRecorderError)ret);
462                     StreamRecorderErrorFactory.ThrowException(ret, "Failed to set audio samplerate");
463                 }
464             }
465         }
466
467         /// <summary>
468         /// The bitrate of an audio encoder in bits per second.
469         /// </summary>
470         /// <remarks>
471         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
472         /// Must set <see cref="StreamRecorderSourceType.Audio"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
473         /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
474         /// </remarks>
475         /// <exception cref="ArgumentException">The value set to below 0.</exception>
476         public int AudioBitRate
477         {
478             get
479             {
480                 int val = 0;
481
482                 int ret = Native.GetAudioEncoderBitrate(_handle, out val);
483                 if ((StreamRecorderError)ret != StreamRecorderError.None)
484                 {
485                     Log.Error(StreamRecorderLog.Tag, "Failed to get audio bitrate, " + (StreamRecorderError)ret);
486                 }
487                 return val;
488             }
489             set
490             {
491                 int ret = Native.SetAudioEncoderBitrate(_handle, value);
492                 if ((StreamRecorderError)ret != StreamRecorderError.None)
493                 {
494                     Log.Error(StreamRecorderLog.Tag, "Failed to set audio bitrate, " + (StreamRecorderError)ret);
495                     StreamRecorderErrorFactory.ThrowException(ret, "Failed to set audio bitrate");
496                 }
497             }
498         }
499
500         /// <summary>
501         /// The bitrate of an video encoder in bits per second.
502         /// </summary>
503         /// <remarks>
504         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
505         /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
506         /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
507         /// </remarks>
508         /// <exception cref="ArgumentException">The value set to below 0.</exception>
509         public int VideoBitRate
510         {
511             get
512             {
513                 int val = 0;
514
515                 int ret = Native.GetVideoEncoderBitrate(_handle, out val);
516                 if ((StreamRecorderError)ret != StreamRecorderError.None)
517                 {
518                     Log.Error(StreamRecorderLog.Tag, "Failed to get video bitrate, " + (StreamRecorderError)ret);
519                 }
520                 return val;
521             }
522             set
523             {
524                 int ret = Native.SetVideoEncoderBitrate(_handle, value);
525                 if ((StreamRecorderError)ret != StreamRecorderError.None)
526                 {
527                     Log.Error(StreamRecorderLog.Tag, "Failed to set video bitrate, " + (StreamRecorderError)ret);
528                     StreamRecorderErrorFactory.ThrowException(ret, "Failed to set video bitrate");
529                 }
530             }
531         }
532
533         /// <summary>
534         /// The video frame rate for recording media stream.
535         /// </summary>
536         /// <remarks>
537         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
538         /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
539         /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
540         /// </remarks>
541         /// <exception cref="NotSupportedException">The value set to below 0.</exception>
542         public int VideoFrameRate
543         {
544             get
545             {
546                 int val = 0;
547
548                 int ret = Native.GetVideoFramerate(_handle, out val);
549                 if ((StreamRecorderError)ret != StreamRecorderError.None)
550                 {
551                     Log.Error(StreamRecorderLog.Tag, "Failed to get video framerate, " + (StreamRecorderError)ret);
552                 }
553                 return val;
554             }
555             set
556             {
557                 int ret = Native.SetVideoFramerate(_handle, value);
558                 if ((StreamRecorderError)ret != StreamRecorderError.None)
559                 {
560                     Log.Error(StreamRecorderLog.Tag, "Failed to set video framerate, " + (StreamRecorderError)ret);
561                     StreamRecorderErrorFactory.ThrowException(ret);
562                 }
563             }
564         }
565
566         /// <summary>
567         /// Get or Set the video source format for recording media stream.
568         /// </summary>
569         /// <exception cref="ArgumentException">The value set to a invalid value.</exception>
570         /// <seealso cref="StreamRecorderVideoSourceFormat"/>
571         public StreamRecorderVideoSourceFormat VideoSourceFormat
572         {
573             get
574             {
575                 int val = 0;
576
577                 int ret = Native.GetVideoSourceFormat(_handle, out val);
578                 if ((StreamRecorderError)ret != StreamRecorderError.None)
579                 {
580                     Log.Error(StreamRecorderLog.Tag, "Failed to get video framerate, " + (StreamRecorderError)ret);
581                 }
582                 return (StreamRecorderVideoSourceFormat)val;
583             }
584             set
585             {
586                 int ret = Native.SetVideoSourceFormat(_handle, (int)value);
587                 if ((StreamRecorderError)ret != StreamRecorderError.None)
588                 {
589                     Log.Error(StreamRecorderLog.Tag, "Failed to set video framerate, " + (StreamRecorderError)ret);
590                     StreamRecorderErrorFactory.ThrowException(ret);
591                 }
592             }
593         }
594
595         /// <summary>
596         /// The number of audio channel.
597         /// </summary>
598         /// <remarks>
599         /// The attribute is applied only in Created state.
600         /// For mono recording, set channel to 1.
601         /// For stereo recording, set channel to 2.
602         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
603         /// </remarks>
604         /// <exception cref="ArgumentException">The value set to a invalid value.</exception>
605         public int AudioChannel
606         {
607             get
608             {
609                 int val = 0;
610
611                 int ret = Native.GetAudioChannel(_handle, out val);
612                 if ((StreamRecorderError)ret != StreamRecorderError.None)
613                 {
614                     Log.Error(StreamRecorderLog.Tag, "Failed to get audio channel, " + (StreamRecorderError)ret);
615                 }
616                 return val;
617             }
618             set
619             {
620                 int ret = Native.SetAudioChannel(_handle, value);
621                 if ((StreamRecorderError)ret != StreamRecorderError.None)
622                 {
623                     Log.Error(StreamRecorderLog.Tag, "Failed to set audio channel, " + (StreamRecorderError)ret);
624                     StreamRecorderErrorFactory.ThrowException(ret, "Failed to set audio channel");
625                 }
626             }
627         }
628
629         /// <summary>
630         /// Video resolution of the video recording.
631         /// </summary>
632         /// <remarks>
633         /// Must set <see cref="StreamRecorderSourceType.Video"/> or <see cref="StreamRecorderSourceType.VideoAudio"/>
634         /// by <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>
635         /// The recorder state must be <see cref="StreamRecorderState.Created"/> state.
636         /// </remarks>
637         /// <exception cref="ArgumentException">The value set to a invalid value.</exception>
638         /// <seealso cref="SupportedVideoResolutions"/>
639         public StreamRecorderVideoResolution Resolution
640         {
641             get
642             {
643                 return _videoResolution;
644             }
645         }
646
647         /// <summary>
648         /// Retrieves all the file formats supported by the stream recorder.
649         /// </summary>
650         /// <returns>
651         /// It returns a list containing all the supported file
652         /// formats by Stream recorder.
653         /// </returns>
654         /// <seealso cref="StreamRecorderFileFormat"/>
655         public IEnumerable<StreamRecorderFileFormat> SupportedFileFormats
656         {
657             get
658             {
659                 if (_formats.Count == 0)
660                 {
661                     Native.FileFormatCallback callback = (StreamRecorderFileFormat format, IntPtr userData) =>
662                     {
663                         _formats.Add(format);
664                         return true;
665                     };
666                     int ret = Native.FileFormats(_handle, callback, IntPtr.Zero);
667                     if (ret != (int)StreamRecorderError.None)
668                     {
669                         StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported fileformats");
670                     }
671                 }
672                 return _formats;
673             }
674         }
675
676         /// <summary>
677         /// Retrieves all the audio encoders supported by the recorder.
678         /// </summary>
679         /// <returns>
680         /// It returns a list containing all the supported audio encoders
681         /// by recorder.
682         /// </returns>
683         /// <seealso cref="StreamRecorderAudioCodec"/>
684         public IEnumerable<StreamRecorderAudioCodec> SupportedAudioEncodings
685         {
686             get
687             {
688                 if (_audioCodec.Count == 0)
689                 {
690                     Native.AudioEncoderCallback callback = (StreamRecorderAudioCodec codec, IntPtr userData) =>
691                     {
692                         _audioCodec.Add(codec);
693                         return true;
694                     };
695                     int ret = Native.AudioEncoders(_handle, callback, IntPtr.Zero);
696                     if (ret != (int)StreamRecorderError.None)
697                     {
698                         StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported audio encoders");
699                     }
700                 }
701                 return _audioCodec;
702             }
703         }
704
705         /// <summary>
706         /// Retrieves all the video encoders supported by the recorder.
707         /// </summary>
708         /// <returns>
709         /// It returns a list containing all the supported video encoders
710         /// by recorder.
711         /// </returns>
712         /// <seealso cref="StreamRecorderVideoCodec"/>
713         public IEnumerable<StreamRecorderVideoCodec> SupportedVideoEncodings
714         {
715             get
716             {
717                 if (_videoCodec.Count == 0)
718                 {
719                     Native.VideoEncoderCallback callback = (StreamRecorderVideoCodec codec, IntPtr userData) =>
720                     {
721                         _videoCodec.Add(codec);
722                         return true;
723                     };
724                     int ret = Native.VideoEncoders(_handle, callback, IntPtr.Zero);
725                     if (ret != (int)StreamRecorderError.None)
726                     {
727                         StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported video encoders");
728                     }
729                 }
730                 return _videoCodec;
731             }
732         }
733
734         /// <summary>
735         /// Retrieves all the video resolutions supported by the recorder.
736         /// </summary>
737         /// <returns>
738         /// It returns videoresolution list containing the width and height of
739         /// different resolutions supported by recorder.
740         /// </returns>
741         /// <seealso cref="StreamRecorderVideoResolution"/>
742         public IEnumerable<StreamRecorderVideoResolution> SupportedVideoResolutions
743         {
744             get
745             {
746                 if (_resolutions.Count == 0)
747                 {
748                     Native.VideoResolutionCallback callback = (int width, int height, IntPtr userData) =>
749                     {
750                         StreamRecorderVideoResolution temp = new StreamRecorderVideoResolution(width, height);
751                         _resolutions.Add(temp);
752                         return true;
753                     };
754                     int ret = Native.VideoResolution(_handle, callback, IntPtr.Zero);
755                     if (ret != (int)StreamRecorderError.None)
756                     {
757                         StreamRecorderErrorFactory.ThrowException(ret, "Failed to get the supported video resolutions");
758                     }
759                 }
760                 return _resolutions;
761             }
762         }
763
764         /// <summary>
765         /// Prepare the stream recorder.
766         /// </summary>
767         /// <remarks>
768         /// Before calling the function, it is required to set <see cref="StreamRecorder.EnableSourceBuffer(StreamRecorderSourceType)"/>,
769         /// <see cref="StreamRecorderAudioCodec"/>, <see cref="StreamRecorderVideoCodec"/> and <see cref="StreamRecorderFileFormat"/> properties of recorder.
770         /// </remarks>
771         /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
772         /// <seealso cref="Unprepare"/>
773         public void Prepare()
774         {
775             int ret = Native.Prepare(_handle);
776             if (ret != (int)StreamRecorderError.None)
777             {
778                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to prepare stream recorder");
779             }
780         }
781
782         /// <summary>
783         /// Resets the stream recorder.
784         /// </summary>
785         /// <remarks>
786         /// The recorder state must be <see cref="StreamRecorderState.Prepared"/> state by <see cref="Prepare"/>, <see cref="Cancel"/> and <see cref="Commit"/>.
787         /// The StreamRecorder state will be <see cref="StreamRecorderState.Created"/>.
788         /// </remarks>
789         /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
790         /// <seealso cref="Prepare"/>
791         public void Unprepare()
792         {
793             int ret = Native.Unprepare(_handle);
794             if (ret != (int)StreamRecorderError.None)
795             {
796                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to reset the stream recorder");
797             }
798         }
799
800         /// <summary>
801         /// Starts the recording.
802         /// </summary>
803         /// <remarks>
804         /// If file path has been set to an existing file, this file is removed automatically and updated by new one.
805         ///     The filename should be set before this function is invoked.
806         ///     The recorder state must be <see cref="StreamRecorderState.Prepared"/> state by <see cref="Prepare"/> or
807         ///     <see cref="StreamRecorderState.Paused"/> state by <see cref="Pause"/>.
808         ///     The filename shuild be set by <see cref="FilePath"/>
809         /// </remarks>
810         /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
811         /// <exception cref="UnauthorizedAccessException">The access ot the resources can not be granted.</exception>
812         /// <seealso cref="Pause"/>
813         /// <seealso cref="Commit"/>
814         /// <seealso cref="Cancel"/>
815         /// <seealso cref="FilePath"/>
816         /// <seealso cref="FileFormat"/>
817         public void Start()
818         {
819             int ret = Native.Start(_handle);
820             if (ret != (int)StreamRecorderError.None)
821             {
822                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to start the stream recorder");
823             }
824         }
825
826         /// <summary>
827         /// Pause the recording.
828         /// </summary>
829         /// <remarks>
830         /// Recording can be resumed with <see cref="Start"/>.
831         /// </remarks>
832         /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
833         /// <seealso cref="Start"/>
834         /// <seealso cref="Commit"/>
835         /// <seealso cref="Cancel"/>
836         public void Pause()
837         {
838             int ret = Native.Pause(_handle);
839             if (ret != (int)StreamRecorderError.None)
840             {
841                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to pause the stream recorder");
842             }
843         }
844
845         /// <summary>
846         /// Stops recording and saves the result.
847         /// </summary>
848         /// <remarks>
849         /// The recorder state must be <see cref="StreamRecorderState.Recording"/> state by <see cref="Start"/> or
850         ///  <see cref="StreamRecorderState.Paused"/> state by <see cref="Pause"/>
851         /// When you want to record audio or video file, you need to add privilege according to rules below additionally.
852         /// <para>
853         /// http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage.
854         /// http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage.
855         /// </para>
856         /// </remarks>
857         /// <exception cref="InvalidOperationException">The streamrecorder is not in the valid state.</exception>
858         /// <exception cref="UnauthorizedAccessException">The access ot the resources can not be granted.</exception>
859         /// <seealso cref="Start"/>
860         /// <seealso cref="Pause"/>
861         public void Commit()
862         {
863             int ret = Native.Commit(_handle);
864             if (ret != (int)StreamRecorderError.None)
865             {
866                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to save the recorded content");
867             }
868         }
869
870         /// <summary>
871         /// Cancels the recording.
872         /// The recording data is discarded and not written in the recording file.
873         /// </summary>
874         /// <seealso cref="Start"/>
875         /// <seealso cref="Pause"/>
876         public void Cancel()
877         {
878             int ret = Native.Cancel(_handle);
879             if (ret != (int)StreamRecorderError.None)
880             {
881                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to cancel the recording");
882             }
883         }
884
885         /// <summary>
886         /// Push stream buffer as recording raw data.
887         /// </summary>
888         public void PushBuffer(MediaPacket packet)
889         {
890             IntPtr _packet_h = packet.GetHandle();
891
892             Log.Info("Tizen.Multimedia.StreamRecorder", "PUSH stream buffer");
893             int ret = Native.PushStreamBuffer(_handle, _packet_h);
894             if (ret != (int)StreamRecorderError.None)
895             {
896                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to push buffer");
897             }
898             Log.Info("Tizen.Multimedia.StreamRecorder", "PUSH stream buffer END");
899         }
900
901         /// <summary>
902         /// Set the source type of pushed data.
903         /// </summary>
904         public void EnableSourceBuffer(StreamRecorderSourceType type)
905         {
906             int ret = Native.EnableSourceBuffer(_handle, (int)type);
907             if (ret != (int)StreamRecorderError.None)
908             {
909                 StreamRecorderErrorFactory.ThrowException(ret, "Failed to set EnableSourceBuffer");
910             }
911         }
912
913         /// <summary>
914         /// Release any unmanaged resources used by this object.
915         /// </summary>
916         public void Dispose()
917         {
918             Dispose(true);
919             GC.SuppressFinalize(this);
920         }
921
922         protected virtual void Dispose(bool disposing)
923         {
924             if (!_disposed)
925             {
926                 if (disposing)
927                 {
928                     // to be used if there are any other disposable objects
929                 }
930                 if (_handle != IntPtr.Zero)
931                 {
932                     Native.Destroy(_handle);
933                     _handle = IntPtr.Zero;
934                 }
935                 _disposed = true;
936             }
937         }
938
939         private void RegisterStreamRecorderNotifiedEvent()
940         {
941             _notifiedCallback = (StreamRecorderState previous, StreamRecorderState current, StreamRecorderNotify notify, IntPtr userData) =>
942             {
943                 StreamRecorderNotifiedEventArgs eventArgs = new StreamRecorderNotifiedEventArgs(previous, current, notify);
944                 _recorderNotified?.Invoke(this, eventArgs);
945             };
946             int ret = Native.SetNotifiedCallback(_handle, _notifiedCallback, IntPtr.Zero);
947             if (ret != (int)StreamRecorderError.None)
948             {
949                 StreamRecorderErrorFactory.ThrowException(ret, "Setting notify callback failed");
950             }
951         }
952
953         private void UnregisterStreamRecorderNotifiedEvent()
954         {
955             int ret = Native.UnsetNotifiedCallback(_handle);
956             if (ret != (int)StreamRecorderError.None)
957             {
958                 StreamRecorderErrorFactory.ThrowException(ret, "Unsetting notify callback failed");
959             }
960         }
961
962         private void RegisterBufferComsumedEvent()
963         {
964             _bufferConsumedCallback = (IntPtr buffer, IntPtr userData) =>
965             {
966                 StreamRecordingBufferConsumedEventArgs eventArgs = new StreamRecordingBufferConsumedEventArgs(buffer);
967                 _bufferConsumed?.Invoke(this, eventArgs);
968             };
969             int ret = Native.SetBufferConsumedCallback(_handle, _bufferConsumedCallback, IntPtr.Zero);
970             if (ret != (int)StreamRecorderError.None)
971             {
972                 StreamRecorderErrorFactory.ThrowException(ret, "Setting buffer consumed callback failed");
973             }
974         }
975
976         private void UnregisterBufferComsumedEvent()
977         {
978             int ret = Native.UnsetBufferConsumedCallback(_handle);
979             if (ret != (int)StreamRecorderError.None)
980             {
981                 StreamRecorderErrorFactory.ThrowException(ret, "Unsetting buffer consumed callback failed");
982             }
983         }
984
985         private void RegisterRecordingStatusChangedEvent()
986         {
987             _recordingStatusCallback = (ulong elapsedTime, ulong fileSize, IntPtr userData) =>
988             {
989                 RecordingProgressEventArgs eventArgs = new RecordingProgressEventArgs(elapsedTime, fileSize);
990                 _recordingStatusChanged?.Invoke(this, eventArgs);
991             };
992             int ret = Native.SetStatusChangedCallback(_handle, _recordingStatusCallback, IntPtr.Zero);
993             if (ret != (int)StreamRecorderError.None)
994             {
995                 StreamRecorderErrorFactory.ThrowException(ret, "Setting status changed callback failed");
996             }
997         }
998
999         private void UnregisterRecordingStatusChangedEvent()
1000         {
1001             int ret = Native.UnsetStatusChangedCallback(_handle);
1002             if (ret != (int)StreamRecorderError.None)
1003             {
1004                 StreamRecorderErrorFactory.ThrowException(ret, "Unsetting status changed callback failed");
1005             }
1006         }
1007
1008         private void RegisterRecordingLimitReachedEvent()
1009         {
1010             _recordingLimitReachedCallback = (StreamRecordingLimitType type, IntPtr userData) =>
1011             {
1012                 StreamRecordingLimitReachedEventArgs eventArgs = new StreamRecordingLimitReachedEventArgs(type);
1013                 _recordingLimitReached?.Invoke(this, eventArgs);
1014             };
1015             int ret = Native.SetLimitReachedCallback(_handle, _recordingLimitReachedCallback, IntPtr.Zero);
1016             if (ret != (int)StreamRecorderError.None)
1017             {
1018                 StreamRecorderErrorFactory.ThrowException(ret, "Setting limit reached callback failed");
1019             }
1020         }
1021
1022         private void UnregisterRecordingLimitReachedEvent()
1023         {
1024             int ret = Native.UnsetLimitReachedCallback(_handle);
1025             if (ret != (int)StreamRecorderError.None)
1026             {
1027                 StreamRecorderErrorFactory.ThrowException(ret, "Unsetting limit reached callback failed");
1028             }
1029         }
1030
1031         private void RegisterRecordingErrorOccurredEvent()
1032         {
1033             _recorderErrorCallback = (StreamRecorderErrorCode error, StreamRecorderState current, IntPtr userData) =>
1034             {
1035                 StreamRecordingErrorOccurredEventArgs eventArgs = new StreamRecordingErrorOccurredEventArgs(error, current);
1036                 _recordingErrorOccurred?.Invoke(this, eventArgs);
1037             };
1038             int ret = Native.SetErrorCallback(_handle, _recorderErrorCallback, IntPtr.Zero);
1039             if (ret != (int)StreamRecorderError.None)
1040             {
1041                 StreamRecorderErrorFactory.ThrowException(ret, "Setting Error callback failed");
1042             }
1043         }
1044
1045         private void UnregisterRecordingErrorOccurredEvent()
1046         {
1047             int ret = Native.UnsetErrorCallback(_handle);
1048             if (ret != (int)StreamRecorderError.None)
1049             {
1050                 StreamRecorderErrorFactory.ThrowException(ret, "Unsetting Error callback failed");
1051             }
1052         }
1053     }
1054 }