Release 4.0.0-preview1-00205
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Recorder / Recorder / VideoRecorder.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.Diagnostics;
19 using Native = Interop.Recorder;
20 using NativeHandle = Interop.RecorderHandle;
21
22 namespace Tizen.Multimedia
23 {
24     /// <summary>
25     /// Provides the ability to control video recording.
26     /// </summary>
27     public partial class VideoRecorder : Recorder
28     {
29         private static NativeHandle CreateHandle(Camera camera)
30         {
31             if (camera == null)
32             {
33                 throw new ArgumentNullException(nameof(camera));
34             }
35
36             Native.CreateVideo(camera.Handle, out var handle).
37                 ThrowIfError("Failed to create video recorder.");
38
39             return handle;
40         }
41
42         private static void ThrowIfCodecAndFormatNotValid(RecorderVideoCodec videoCodec,
43             RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat)
44         {
45             videoCodec.ThrowIfFormatNotSupported(fileFormat);
46
47             if (audioCodec != RecorderAudioCodec.None)
48             {
49                 audioCodec.ThrowIfFormatNotSupported(fileFormat);
50             }
51         }
52
53         /// <summary>
54         /// Initializes a new instance of the <see cref="VideoRecorder"/> class with the specified camera, video codec and file format.
55         /// </summary>
56         /// <remarks>
57         /// If the state of <see cref="Camera"/> is <see cref="CameraState.Created"/>,
58         /// the <see cref="CameraSettings.PreviewPixelFormat"/> will be changed to the recommended format for recording.\n
59         /// \n
60         /// The initial state of the Recorder will be <see cref="RecorderState.Ready"/>
61         /// if the state of <see cref="Camera"/> is <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/>.
62         /// </remarks>
63         /// <param name="camera">The camera object.</param>
64         /// <param name="videoCodec">The codec for video encoding.</param>
65         /// <param name="fileFormat">The format of result file.</param>
66         /// <feature>http://tizen.org/feature/camera</feature>
67         /// <exception cref="InvalidOperationException">An internal error occurred.</exception>
68         /// <exception cref="NotSupportedException">
69         ///     A required feature is not supported.\n
70         ///     -or-\n
71         ///     <paramref name="videoCodec"/> is not supported.\n
72         ///     -or-\n
73         ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
74         /// </exception>
75         /// <exception cref="ArgumentException">
76         ///     <paramref name="videoCodec"/> is not valid.\n
77         ///     -or-\n
78         ///     <paramref name="fileFormat"/> is not valid.
79         /// </exception>
80         /// <exception cref="ObjectDisposedException"><paramref name="camera"/> has been disposed of.</exception>
81         /// <exception cref="ArgumentNullException"><paramref name="camera"/> is null.</exception>
82         /// <seealso cref="GetSupportedVideoCodecs"/>
83         /// <seealso cref="Recorder.GetSupportedFileFormats"/>
84         /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
85         /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderFileFormat)"/>
86         /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderAudioCodec, RecorderFileFormat)"/>
87         public VideoRecorder(Camera camera, RecorderVideoCodec videoCodec, RecorderFileFormat fileFormat) :
88             this(camera, videoCodec, RecorderAudioCodec.None, fileFormat)
89         {
90         }
91
92         /// <summary>
93         /// Initializes a new instance of the <see cref="VideoRecorder"/> class with the specified camera, video codec,
94         /// audio codec and file format.
95         /// </summary>
96         /// <remarks>
97         /// If the state of <see cref="Camera"/> is <see cref="CameraState.Created"/>,
98         /// the <see cref="CameraSettings.PreviewPixelFormat"/> will be changed to the recommended format for recording.\n
99         /// \n
100         /// The initial state of the Recorder will be <see cref="RecorderState.Ready"/>
101         /// if the state of <see cref="Camera"/> is <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/>.
102         /// </remarks>
103         /// <param name="camera">The camera object.</param>
104         /// <param name="videoCodec">The codec for video encoding.</param>
105         /// <param name="audioCodec">The codec for audio encoding.</param>
106         /// <param name="fileFormat">The format of result file.</param>
107         /// <feature>http://tizen.org/feature/camera</feature>
108         /// <exception cref="InvalidOperationException">An internal error occurred.</exception>
109         /// <exception cref="NotSupportedException">
110         ///     A required feature is not supported.\n
111         ///     -or-\n
112         ///     <paramref name="videoCodec"/> is not supported.\n
113         ///     -or-\n
114         ///     <paramref name="audioCodec"/> is not supported.\n
115         ///     -or-\n
116         ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
117         ///     -or-\n
118         ///     <paramref name="fileFormat"/> is not supported with the specified audio codec.
119         /// </exception>
120         /// <exception cref="ArgumentException">
121         ///     <paramref name="videoCodec"/> is not valid.\n
122         ///     -or-\n
123         ///     <paramref name="audioCodec"/> is not valid.\n
124         ///     -or-\n
125         ///     <paramref name="fileFormat"/> is not valid.
126         /// </exception>
127         /// <exception cref="ObjectDisposedException"><paramref name="camera"/> has been disposed of.</exception>
128         /// <exception cref="ArgumentNullException"><paramref name="camera"/> is null.</exception>
129         /// <seealso cref="Recorder.GetSupportedAudioCodecs"/>
130         /// <seealso cref="GetSupportedVideoCodecs"/>
131         /// <seealso cref="Recorder.GetSupportedFileFormats"/>
132         /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderAudioCodec)"/>
133         /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
134         /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderFileFormat)"/>
135         /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderAudioCodec, RecorderFileFormat)"/>
136         public VideoRecorder(Camera camera, RecorderVideoCodec videoCodec,
137             RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat) : base(CreateHandle(camera))
138         {
139             SetFormatAndCodec(videoCodec, RecorderAudioCodec.None, fileFormat);
140         }
141
142         /// <summary>
143         /// Sets the video codec and the file format for recording. Audio will not recorded.
144         /// </summary>
145         /// <param name="videoCodec">The codec for video encoding.</param>
146         /// <param name="fileFormat">The format of result file.</param>
147         /// <exception cref="NotSupportedException">
148         ///     <paramref name="videoCodec"/> is not supported.\n
149         ///     -or-\n
150         ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
151         /// </exception>
152         /// <exception cref="ArgumentException">
153         ///     <paramref name="videoCodec"/> is not valid.\n
154         ///     -or-\n
155         ///     <paramref name="fileFormat"/> is not valid.
156         /// </exception>
157         /// <seealso cref="GetSupportedVideoCodecs"/>
158         /// <seealso cref="Recorder.GetSupportedFileFormats"/>
159         /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
160         /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderAudioCodec, RecorderFileFormat)"/>
161         /// <seealso cref="Recorder.Start(string)"/>
162         public void SetFormatAndCodec(RecorderVideoCodec videoCodec, RecorderFileFormat fileFormat)
163         {
164             SetFormatAndCodec(videoCodec, RecorderAudioCodec.None, fileFormat);
165         }
166
167         /// <summary>
168         /// Sets the video codec, audio codec and the file format for recording.
169         /// </summary>
170         /// <param name="videoCodec">The codec for video encoding.</param>
171         /// <param name="audioCodec">The codec for audio encoding.</param>
172         /// <param name="fileFormat">The format of result file.</param>
173         /// <exception cref="NotSupportedException">
174         ///     <paramref name="videoCodec"/> is not supported.\n
175         ///     -or-\n
176         ///     <paramref name="audioCodec"/> is not supported.\n
177         ///     -or-\n
178         ///     <paramref name="fileFormat"/> is not supported with the specified video codec.
179         ///     -or-\n
180         ///     <paramref name="fileFormat"/> is not supported with the specified audio codec.
181         /// </exception>
182         /// <exception cref="ArgumentException">
183         ///     <paramref name="videoCodec"/> is not valid.\n
184         ///     -or-\n
185         ///     <paramref name="audioCodec"/> is not valid.\n
186         ///     -or-\n
187         ///     <paramref name="fileFormat"/> is not valid.
188         /// </exception>
189         /// <seealso cref="Recorder.GetSupportedAudioCodecs"/>
190         /// <seealso cref="VideoRecorder.GetSupportedVideoCodecs"/>
191         /// <seealso cref="Recorder.GetSupportedFileFormats"/>
192         /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderAudioCodec)"/>
193         /// <seealso cref="RecorderExtensions.GetSupportedFileFormats(RecorderVideoCodec)"/>
194         /// <seealso cref="SetFormatAndCodec(RecorderVideoCodec, RecorderFileFormat)"/>
195         /// <seealso cref="Recorder.Start(string)"/>
196         public void SetFormatAndCodec(RecorderVideoCodec videoCodec, RecorderAudioCodec audioCodec, RecorderFileFormat fileFormat)
197         {
198             ThrowIfCodecAndFormatNotValid(videoCodec, audioCodec, fileFormat);
199
200             VideoCodec = videoCodec;
201             AudioCodec = audioCodec;
202             FileFormat = fileFormat;
203         }
204
205         #region Properties
206
207         private RecorderVideoCodec _videoCodec;
208
209         /// <summary>
210         /// Gets the audio codec for encoding an audio stream.
211         /// </summary>
212         public RecorderVideoCodec VideoCodec
213         {
214             get => _videoCodec;
215             internal set
216             {
217                 Debug.Assert(Enum.IsDefined(typeof(RecorderVideoCodec), value));
218
219                 ValidateVideoCodec(value);
220
221                 Native.SetVideoEncoder(Handle, value).ThrowIfError("Failed to set video codec.");
222
223                 _videoCodec = value;
224             }
225         }
226
227         /// <summary>
228         /// Gets or sets the video recording motion rate.
229         /// </summary>
230         /// <remarks>
231         /// The attribute is valid only in a video recorder.\n
232         /// If the rate is in range of 0-1, the video is recorded in a slow motion mode.\n
233         /// If the rate is bigger than 1, the video is recorded in a fast motion mode.\n
234         /// \n
235         /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or the <see cref="RecorderState.Ready"/> state.
236         /// </remarks>
237         /// <exception cref="ArgumentOutOfRangeException">The <paramref name="value"/> is less than or equal to 0.</exception>
238         /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
239         /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
240         public double VideoMotionRate
241         {
242             get
243             {
244                 Native.GetMotionRate(Handle, out var val).ThrowIfError("Failed to get video motion rate.");
245
246                 return val;
247             }
248
249             set
250             {
251                 ValidateState(RecorderState.Idle, RecorderState.Ready);
252
253                 if (value <= 0)
254                 {
255                     throw new ArgumentOutOfRangeException(nameof(value), value,
256                         "Video Motion rate can't be less than zero.");
257                 }
258
259                 Native.SetMotionRate(Handle, value).
260                     ThrowIfError("Failed to set video motion rate");
261             }
262         }
263
264         /// <summary>
265         /// Gets or sets the orientation in the video metadata tag.
266         /// </summary>
267         /// <value>A <see cref="Rotation"/> that specifies the type of orientation.</value>
268         /// <exception cref="ArgumentException"><paramref name="value"/> is not valid.</exception>
269         /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
270         public Rotation VideoOrientationTag
271         {
272             get
273             {
274                 Native.GetOrientationTag(Handle, out var val).ThrowIfError("Failed to get recorder orientation.");
275
276                 return val;
277             }
278
279             set
280             {
281                 ValidationUtil.ValidateEnum(typeof(Rotation), value, nameof(value));
282
283                 Native.SetOrientationTag(Handle, value).
284                     ThrowIfError("Failed to set recorder orientation");
285             }
286         }
287
288         /// <summary>
289         /// Gets or sets the resolution of the video recording.
290         /// </summary>
291         /// <remarks>
292         /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or the <see cref="RecorderState.Ready"/> state.
293         /// </remarks>
294         /// <exception cref="ArgumentOutOfRangeException">Width or height of <paramref name="value"/> is less than or equal to zero.</exception>
295         /// <exception cref="NotSupportedException"><paramref name="value"> is not supported.</exception>
296         /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
297         /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
298         /// <seealso cref="Recorder.GetSupportedVideoResolutions(CameraDevice)"/>
299         public Size VideoResolution
300         {
301             get
302             {
303                 Native.GetVideoResolution(Handle, out var width, out var height).
304                     ThrowIfError("Failed to get camera video resolution");
305
306                 return new Size(width, height);
307             }
308
309             set
310             {
311                 ValidateState(RecorderState.Idle, RecorderState.Ready);
312
313                 if (value.Width <= 0 || value.Height <= 0)
314                 {
315                     throw new ArgumentOutOfRangeException(nameof(value), value,
316                         "Resolution can't be less than or equal to zero.");
317                 }
318
319                 var ret = Native.SetVideoResolution(Handle, value.Width, value.Height);
320
321                 if (ret == RecorderErrorCode.InvalidParameter)
322                 {
323                     throw new NotSupportedException($"Resolution({value.ToString()}) is not supported.");
324                 }
325
326                 ret.ThrowIfError("Failed to set video resolution.");
327             }
328         }
329
330         /// <summary>
331         /// Gets or sets the bitrate of the video encoder in bits per second.
332         /// </summary>
333         /// <remarks>
334         /// To set, the recorder must be in the <see cref="RecorderState.Idle"/> or <see cref="RecorderState.Ready"/> state.
335         /// </remarks>
336         /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than or equal to zero.</exception>
337         /// <exception cref="InvalidOperationException">The recorder is not in the valid state.</exception>
338         /// <exception cref="ObjectDisposedException">The recorder already has been disposed of.</exception>
339         public int VideoBitRate
340         {
341             get
342             {
343                 Native.GetVideoEncoderBitrate(Handle, out var val).ThrowIfError("Failed to get video bitrate.");
344
345                 return val;
346             }
347
348             set
349             {
350                 ValidateState(RecorderState.Idle, RecorderState.Ready);
351
352                 if (value <= 0)
353                 {
354                     throw new ArgumentOutOfRangeException(nameof(value), value,
355                         "Bit rate can't be less than or equal to zero.");
356                 }
357
358                 Native.SetVideoEncoderBitrate(Handle, value).
359                     ThrowIfError("Failed to set video bitrate");
360             }
361         }
362
363         #endregion
364     }
365 }