Apply video recording bitrate dynamically
[framework/osp/media.git] / src / FMedia_RecorderUtil.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                        FMedia_RecorderUtil.cpp
20  * @brief                       This file contains the utility of camcorder.
21  *
22  */
23
24 #include <FIoFile.h>
25 #include <FBaseSysLog.h>
26 #include "FMedia_RecorderUtil.h"
27
28 using namespace Tizen::Io;
29
30 namespace Tizen { namespace Media
31 {
32
33 typedef struct
34 {
35         Tizen::Media::CodecType audioCodec;
36         Tizen::Media::CodecType videoCodec;
37         Tizen::Media::MediaContainerType container;
38 } _CodecContainerTable;
39
40 const static _CodecContainerTable _SUPPORTED_CODEC_CONTAINER[] =
41 {
42         //Audio
43         { CODEC_LPCM,           CODEC_NONE,             MEDIA_CONTAINER_WAV},
44         { CODEC_AMR_NB,         CODEC_NONE,             MEDIA_CONTAINER_AMR},
45         { CODEC_AMR_NB,         CODEC_NONE,             MEDIA_CONTAINER_3GP},
46 //      { CODEC_AMR_NB,         CODEC_NONE,             MEDIA_CONTAINER_MP4},
47         { CODEC_AAC,            CODEC_NONE,             MEDIA_CONTAINER_AAC},
48         {  CODEC_AAC,           CODEC_NONE,             MEDIA_CONTAINER_3GP},
49         {  CODEC_AAC,           CODEC_NONE,             MEDIA_CONTAINER_MP4},
50
51         // Video
52         { CODEC_AMR_NB,         CODEC_MPEG4,            MEDIA_CONTAINER_3GP},
53         { CODEC_AMR_NB,         CODEC_H263,             MEDIA_CONTAINER_3GP},
54         { CODEC_AMR_NB,         CODEC_H264,             MEDIA_CONTAINER_3GP},
55 //      { CODEC_AMR_NB,         CODEC_MPEG4,            MEDIA_CONTAINER_MP4},
56 //      { CODEC_AMR_NB,         CODEC_H263,             MEDIA_CONTAINER_MP4},
57 //      { CODEC_AMR_NB,         CODEC_H264,             MEDIA_CONTAINER_MP4},
58
59         { CODEC_AAC,    CODEC_MPEG4,            MEDIA_CONTAINER_3GP},
60         { CODEC_AAC,    CODEC_H263,             MEDIA_CONTAINER_3GP},
61         { CODEC_AAC,    CODEC_H264,             MEDIA_CONTAINER_3GP},
62         { CODEC_AAC,    CODEC_MPEG4,            MEDIA_CONTAINER_MP4},
63 //      { CODEC_AAC,    CODEC_H263,             MEDIA_CONTAINER_MP4},
64         { CODEC_AAC,    CODEC_H264,             MEDIA_CONTAINER_MP4},
65
66         { CODEC_NONE,   CODEC_MPEG4,            MEDIA_CONTAINER_3GP},
67         { CODEC_NONE,   CODEC_H263,             MEDIA_CONTAINER_3GP},
68         { CODEC_NONE,   CODEC_H264,             MEDIA_CONTAINER_3GP},
69         { CODEC_NONE,   CODEC_MPEG4,            MEDIA_CONTAINER_MP4},
70 //      { CODEC_NONE,   CODEC_H263,             MEDIA_CONTAINER_MP4},
71         { CODEC_NONE,   CODEC_H264,             MEDIA_CONTAINER_MP4},
72 };
73
74
75 typedef struct
76 {
77         recorder_audio_codec_e mmAttr;
78         CodecType value;
79 }_AudioCodecTable;
80
81 static const _AudioCodecTable _AUDIO_CODEC[] =
82 {
83         {::RECORDER_AUDIO_CODEC_DISABLE, CODEC_NONE},
84         {::RECORDER_AUDIO_CODEC_AMR, CODEC_AMR_NB},
85         {::RECORDER_AUDIO_CODEC_AAC, CODEC_AAC},
86 //      {::RECORDER_AUDIO_CODEC_VORBIS, CODEC_VORBIS},//We do not supported VORBIS CODEC TYPE
87         {::RECORDER_AUDIO_CODEC_PCM, CODEC_LPCM},
88 };
89
90 result
91 _RecorderUtil::GetMmAudioCodec(CodecType value, recorder_audio_codec_e& mmAttr)
92 {
93         bool findFlag = false;
94         int size = sizeof(_AUDIO_CODEC)/sizeof(_AUDIO_CODEC[0]);
95
96         for (int i = 0; i < size; i++)
97         {
98                 if (_AUDIO_CODEC[i].value == value)
99                 {
100                         mmAttr = _AUDIO_CODEC[i].mmAttr;
101                         findFlag = true;
102                         break;
103                 }
104         }
105         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
106 }
107
108 result
109 _RecorderUtil::GetOspAudioCodec(recorder_audio_codec_e mmAttr, CodecType& value)
110 {
111         bool findFlag = false;
112         int size = sizeof(_AUDIO_CODEC)/sizeof(_AUDIO_CODEC[0]);
113
114         for (int i = 0; i < size; i++)
115         {
116                 if (_AUDIO_CODEC[i].mmAttr == mmAttr)
117                 {
118                         value = _AUDIO_CODEC[i].value;
119                         findFlag = true;
120                         break;
121                 }
122         }
123         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
124 }
125
126 typedef struct
127 {
128         recorder_video_codec_e mmAttr;
129         CodecType value;
130 }_VideoCodecTable;
131
132 static const _VideoCodecTable _VIDEO_CODEC[] =
133 {
134         {::RECORDER_VIDEO_CODEC_H263, CODEC_H263},
135         {::RECORDER_VIDEO_CODEC_H264, CODEC_H264},
136         {::RECORDER_VIDEO_CODEC_MPEG4, CODEC_MPEG4},
137 //      {::RECORDER_VIDEO_CODEC_THEORA, CODEC_THEORA},
138 };
139
140 result
141 _RecorderUtil::GetMmVideoCodec(CodecType value, recorder_video_codec_e& mmAttr)
142 {
143         bool findFlag = false;
144         int size = sizeof(_VIDEO_CODEC)/sizeof(_VIDEO_CODEC[0]);
145
146         for (int i = 0; i < size; i++)
147         {
148                 if (_VIDEO_CODEC[i].value == value)
149                 {
150                         mmAttr = _VIDEO_CODEC[i].mmAttr;
151                         findFlag = true;
152                         break;
153                 }
154         }
155         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
156 }
157
158 result
159 _RecorderUtil::GetOspVideoCodec(recorder_video_codec_e mmAttr, CodecType& value)
160 {
161         bool findFlag = false;
162         int size = sizeof(_VIDEO_CODEC)/sizeof(_VIDEO_CODEC[0]);
163
164         for (int i = 0; i < size; i++)
165         {
166                 if (_VIDEO_CODEC[i].mmAttr == mmAttr)
167                 {
168                         value = _VIDEO_CODEC[i].value;
169                         findFlag = true;
170                         break;
171                 }
172         }
173         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
174 }
175
176 typedef struct
177 {
178         recorder_file_format_e mmAttr;
179         MediaContainerType value;
180 }_ContainerTable;
181
182 static const _ContainerTable _CONTAINER[] =
183 {
184         {::RECORDER_FILE_FORMAT_3GP, MEDIA_CONTAINER_3GP},
185         {::RECORDER_FILE_FORMAT_MP4, MEDIA_CONTAINER_MP4},
186         {::RECORDER_FILE_FORMAT_AMR, MEDIA_CONTAINER_AMR},
187         {::RECORDER_FILE_FORMAT_ADTS, MEDIA_CONTAINER_AAC},
188         {::RECORDER_FILE_FORMAT_WAV, MEDIA_CONTAINER_WAV},
189 };
190
191
192 typedef struct
193 {
194                 recorder_file_format_e mmAttr;
195                 MediaContainerType value;
196 }_VideoContainerTable;
197
198 static const _VideoContainerTable _VIDEO_CONTAINER[] =
199 {
200         {::RECORDER_FILE_FORMAT_3GP, MEDIA_CONTAINER_3GP},
201         {::RECORDER_FILE_FORMAT_MP4, MEDIA_CONTAINER_MP4},
202 };
203
204 typedef struct
205 {
206                 recorder_file_format_e mmAttr;
207                 MediaContainerType value;
208 }_ContainerVideoTable;
209
210 result
211 _RecorderUtil::GetMmFileFormat(MediaContainerType value, recorder_file_format_e& mmAttr)
212 {
213         bool findFlag = false;
214         int size = sizeof(_CONTAINER)/sizeof(_CONTAINER[0]);
215
216         for (int i = 0; i < size; i++)
217         {
218                 if (_CONTAINER[i].value == value)
219                 {
220                         mmAttr = _CONTAINER[i].mmAttr;
221                         findFlag = true;
222                         break;
223                 }
224         }
225         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
226 }
227
228 result
229 _RecorderUtil::GetOspVideoContainer(recorder_file_format_e mmAttr, MediaContainerType& value)
230 {
231         bool findFlag = false;
232         int size = sizeof(_VIDEO_CONTAINER)/sizeof(_VIDEO_CONTAINER[0]);
233
234         for (int i = 0; i < size; i++)
235         {
236                 if (_VIDEO_CONTAINER[i].mmAttr == mmAttr)
237                 {
238                         value = _VIDEO_CONTAINER[i].value;
239                         findFlag = true;
240                         break;
241                 }
242         }
243         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
244 }
245
246 result
247 _RecorderUtil::GetOspAudioContainer(recorder_file_format_e mmAttr, MediaContainerType& value)
248 {
249                 bool findFlag = false;
250                 int size = sizeof(_CONTAINER)/sizeof(_CONTAINER[0]);
251
252                 for (int i = 0; i < size; i++)
253                 {
254                                 if (_CONTAINER[i].mmAttr == mmAttr)
255                                 {
256                                                 value = _CONTAINER[i].value;
257                                                 findFlag = true;
258                                                 break;
259                                 }
260                 }
261                 return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
262 }
263
264 typedef struct
265 {
266         int mmAttrSamplerate;
267         int mmAttrChannel;
268         int mmAttrBitrate;
269         CodecType audioCodec;
270         RecordingQuality quality;
271 }_AudioQualityTable;
272
273 static const _AudioQualityTable _AUDIO_QUALITY[] =
274 {
275         {8000, 1, 256000, CODEC_LPCM, RECORDING_QUALITY_LOW},
276         {22050, 2, 706000, CODEC_LPCM, RECORDING_QUALITY_MEDIUM},
277         {44100, 2, 1411000, CODEC_LPCM, RECORDING_QUALITY_HIGH},
278         {8000, 1, 4750, CODEC_AMR_NB, RECORDING_QUALITY_LOW},
279         {8000, 1, 7950, CODEC_AMR_NB, RECORDING_QUALITY_MEDIUM},
280         {8000, 1, 12200, CODEC_AMR_NB, RECORDING_QUALITY_HIGH},
281         {22050, 2, 120000, CODEC_AAC, RECORDING_QUALITY_LOW},
282         {44100, 2, 220000, CODEC_AAC, RECORDING_QUALITY_MEDIUM},
283         {44100, 2, 320000, CODEC_AAC, RECORDING_QUALITY_HIGH},
284 };
285
286 result
287 _RecorderUtil::GetMmAudioQuality(CodecType audioCodec, RecordingQuality quality, int& mmAttrSamplerate, int& mmAttrChannel, int& mmAttrBitrate)
288 {
289         bool findFlag = false;
290         int size = sizeof(_AUDIO_QUALITY)/sizeof(_AUDIO_QUALITY[0]);
291
292         for (int i = 0; i < size; i++)
293         {
294                 if (_AUDIO_QUALITY[i].audioCodec == audioCodec && _AUDIO_QUALITY[i].quality == quality)
295                 {
296                         mmAttrSamplerate = _AUDIO_QUALITY[i].mmAttrSamplerate;
297                         mmAttrChannel = _AUDIO_QUALITY[i].mmAttrChannel;
298                         mmAttrBitrate = _AUDIO_QUALITY[i].mmAttrBitrate;
299                         findFlag = true;
300                         break;
301                 }
302         }
303         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
304 }
305
306 typedef struct
307 {
308         int mmAttrBitrate;
309         int width;              //max boundary
310         int height;             // min boundary
311         RecordingQuality quality;
312 }_VideoQualityTable;
313
314 static const _VideoQualityTable _VIDEO_QUALITY[] =
315 {
316         {48000, 128, 96, RECORDING_QUALITY_LOW},
317         {64000, 128, 96, RECORDING_QUALITY_MEDIUM},
318         {80000, 128, 96, RECORDING_QUALITY_HIGH},
319
320         {72000, 162, 120, RECORDING_QUALITY_LOW},
321         {97000, 160, 120, RECORDING_QUALITY_MEDIUM},
322         {120000, 160, 120, RECORDING_QUALITY_HIGH},
323
324         {96000, 800, 600, RECORDING_QUALITY_LOW},
325         {128000, 800, 600, RECORDING_QUALITY_MEDIUM},
326         {160000, 800, 600, RECORDING_QUALITY_HIGH},
327
328         {96000, 0xfffe, 0xfffe, RECORDING_QUALITY_LOW},
329         {160000, 0xfffe, 0xfffe, RECORDING_QUALITY_MEDIUM},
330         {4000000, 0xfffe, 0xfffe, RECORDING_QUALITY_HIGH},
331 };
332
333 result
334 _RecorderUtil::GetMmVideoQuality(const Tizen::Graphics::Dimension& dim, RecordingQuality quality, int& mmAttrBitrate)
335 {
336         bool findFlag = false;
337         int size = sizeof(_VIDEO_QUALITY)/sizeof(_VIDEO_QUALITY[0]);
338
339         for (int i = 0; i < size; i++)
340         {
341                 if (_VIDEO_QUALITY[i].width >= dim.width && _VIDEO_QUALITY[i].height >= dim.height && _VIDEO_QUALITY[i].quality == quality)
342                 {
343                         mmAttrBitrate = _VIDEO_QUALITY[i].mmAttrBitrate;
344                         findFlag = true;
345                         break;
346                 }
347         }
348         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
349 }
350
351 typedef struct
352 {
353         recorder_rotation_e mmAttr;
354         RecordingRotation value;
355 }_RotationTable;
356
357 static const _RotationTable _ROTATION[] =
358 {
359         {RECORDER_ROTATION_NONE, RECORDING_ROTATION_NONE},
360         {RECORDER_ROTATION_90, RECORDING_ROTATION_90},
361         {RECORDER_ROTATION_180, RECORDING_ROTATION_180},
362         {RECORDER_ROTATION_270, RECORDING_ROTATION_270},
363 };
364
365 result
366 _RecorderUtil::GetMmRotation(RecordingRotation value, recorder_rotation_e& mmAttr)
367 {
368         bool findFlag = false;
369         int size = sizeof(_ROTATION)/sizeof(_ROTATION[0]);
370
371         for (int i = 0; i < size; i++)
372         {
373                 if (_ROTATION[i].value == value)
374                 {
375                         mmAttr = _ROTATION[i].mmAttr;
376                         findFlag = true;
377                         break;
378                 }
379         }
380         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
381 }
382
383 result
384 _RecorderUtil::GetOspRotation(recorder_rotation_e mmAttr, RecordingRotation& value)
385 {
386         bool findFlag = false;
387         int size = sizeof(_ROTATION)/sizeof(_ROTATION[0]);
388
389         for (int i = 0; i < size; i++)
390         {
391                 if (_ROTATION[i].mmAttr == mmAttr)
392                 {
393                         value = _ROTATION[i].value;
394                         findFlag = true;
395                         break;
396                 }
397         }
398         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
399 }
400
401 typedef struct
402 {
403         CameraRotation cameraRotation;
404         RecordingRotation recorderRotation;
405 }CameraRecorderRotationTable;
406
407 static const CameraRecorderRotationTable _CAM_REC_ROTATION[] =
408 {
409         {CAMERA_ROTATION_NONE, RECORDING_ROTATION_NONE},
410         {CAMERA_ROTATION_90, RECORDING_ROTATION_90},
411         {CAMERA_ROTATION_180, RECORDING_ROTATION_180},
412         {CAMERA_ROTATION_270, RECORDING_ROTATION_270},
413 };
414
415 result
416 _RecorderUtil::GetRecorderRotation(CameraRotation cameraRotation, RecordingRotation& recorderRotation)
417 {
418         bool findFlag = false;
419         int size = sizeof(_CAM_REC_ROTATION)/sizeof(_CAM_REC_ROTATION[0]);
420
421         for (int i = 0; i < size; i++)
422         {
423                 if (_CAM_REC_ROTATION[i].cameraRotation == cameraRotation)
424                 {
425                         recorderRotation = _CAM_REC_ROTATION[i].recorderRotation;
426                         findFlag = true;
427                         break;
428                 }
429         }
430         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
431 }
432
433 result
434 _RecorderUtil::GetCameraRotation(RecordingRotation recorderRotation, CameraRotation& cameraRotation)
435 {
436         bool findFlag = false;
437         int size = sizeof(_CAM_REC_ROTATION)/sizeof(_CAM_REC_ROTATION[0]);
438
439         for (int i = 0; i < size; i++)
440         {
441                 if (_CAM_REC_ROTATION[i].recorderRotation == recorderRotation)
442                 {
443                         cameraRotation = _CAM_REC_ROTATION[i].cameraRotation;
444                         findFlag = true;
445                         break;
446                 }
447         }
448         return findFlag ? E_SUCCESS : E_UNSUPPORTED_TYPE;
449 }
450
451 bool
452 _RecorderUtil::CheckFormat(CodecType audioCodec, CodecType videoCodec, MediaContainerType container)
453 {
454         bool supported = false;
455         int tableCount = 0;
456         tableCount = sizeof(_SUPPORTED_CODEC_CONTAINER) / sizeof(_SUPPORTED_CODEC_CONTAINER[0]);
457
458         for (int i = 0; i < tableCount; i++)
459         {
460                 if (audioCodec == _SUPPORTED_CODEC_CONTAINER[i].audioCodec && videoCodec == _SUPPORTED_CODEC_CONTAINER[i].videoCodec && container == _SUPPORTED_CODEC_CONTAINER[i].container)
461                 {
462                         supported = true;
463                         break;
464                 }
465         }
466         return supported;
467 }
468
469 result
470 _RecorderUtil::PrepareFile(const Tizen::Base::String& path, bool overwrite)
471 {
472         result r = E_SUCCESS;
473
474         if (File::IsFileExist(path))
475         {
476                 if (overwrite)
477                 {
478                         r = File::Remove(path);
479                         SysSecureTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] camcorder remove existing file failed. path:%ls", GetErrorMessage(r), path.GetPointer());
480                 }
481                 else
482                 {
483                         r = E_FILE_ALREADY_EXIST;
484                         SysSecureLogException(NID_MEDIA, r, "[E_FILE_ALREADY_EXIST] The file already exists and overwrite is false. path:%ls", path.GetPointer());
485                         goto CATCH;
486                 }
487         }
488         else
489         {
490                 File file;
491                 r = file.Construct(path, L"w");
492                 SysSecureTryCatch(NID_MEDIA, r == E_SUCCESS, r = E_RESOURCE_UNAVAILABLE, E_RESOURCE_UNAVAILABLE, "[E_RESOURCE_UNAVAILABLE] The file path is not available. path:%ls", path.GetPointer());
493                 r = File::Remove(path);
494                 SysSecureTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] camcorder remove temp file failed. path:%ls", GetErrorMessage(r), path.GetPointer());
495         }
496
497         return r;
498
499 CATCH:
500         return r;
501 }
502
503 AudioSampleType
504 _RecorderUtil::GetOspSampleType(audio_sample_type_e audioSampleType)
505 {
506         switch (audioSampleType)
507         {
508         case AUDIO_SAMPLE_TYPE_U8:
509                 return AUDIO_TYPE_PCM_U8;
510                 break;
511
512         case AUDIO_SAMPLE_TYPE_S16_LE:
513                 return AUDIO_TYPE_PCM_S16_LE;
514                 break;
515
516         default:
517                 return AUDIO_TYPE_PCM_S16_LE;
518                 break;
519         }
520 }
521
522 AudioChannelType
523 _RecorderUtil::GetOspChannelType(int audioChannelType)
524 {
525         switch (audioChannelType)
526         {
527         case 1:
528                 return AUDIO_CHANNEL_TYPE_MONO;
529                 break;
530
531         case 2:
532                 return AUDIO_CHANNEL_TYPE_STEREO;
533                 break;
534
535         default:
536                 return AUDIO_CHANNEL_TYPE_NONE;
537                 break;
538         }
539 }
540
541 int
542 _RecorderUtil::ConvertAudioSampleTypeToInt(AudioSampleType sampleType)
543 {
544         int bitDepth = 0;
545         switch(sampleType)
546         {
547                 case AUDIO_TYPE_NONE:
548                         bitDepth =  0;
549                         break;
550                 case AUDIO_TYPE_PCM_S8:
551                         //fall through
552                 case AUDIO_TYPE_PCM_U8:
553                         bitDepth =  8;
554                         break;
555                 case AUDIO_TYPE_PCM_U16_LE:
556                         //fall through
557                 case AUDIO_TYPE_PCM_S16_LE:
558                         //fall through
559                 case AUDIO_TYPE_PCM_S16_BE:
560                         //fall through
561                 case AUDIO_TYPE_PCM_U16_BE:
562                         bitDepth =  16;
563                         break;
564                 default:
565                         bitDepth =  16;
566                         break;
567         }
568         return bitDepth;
569 }
570
571 int
572 _RecorderUtil::CalculateSampleRate(int size, int channel, int timeStamp, AudioSampleType sampleType)
573 {
574         //bitRate = sample Rate * bitDepth * No of Channel;
575
576         SysTryReturn(NID_MEDIA, timeStamp != 0, 0, E_INVALID_DATA, "[E_INVALID_DATA] Sampling rate cannot be calculated");
577
578         int bitRate = 0;
579         int bitDepth = 0;
580         int sampleRate = 0;
581
582         bitRate =  (size * 1000 * 8)/timeStamp; // convert from bytes to bits for "Packet duration" mili sec of data
583
584         bitDepth = ConvertAudioSampleTypeToInt(sampleType);
585         sampleRate = (bitRate / (bitDepth * channel));
586
587         return sampleRate;
588 }
589
590 }}// Tizen::Media