45 |
48 |
46 |
49 |
47 // constants |
50 // constants |
48 namespace |
51 namespace |
49 { |
52 { |
50 // Controller UId, can be used by the client to identify the controller, e.g. if the custom command can be used |
|
51 const TUid KCamCControllerImplementationUid = {0x101F8503}; |
|
52 // TMMFEvent UIDs for Async stop |
53 // TMMFEvent UIDs for Async stop |
53 const TUid KCamCControllerCCVideoRecordStopped = {0x2000E546}; |
54 const TUid KCamCControllerCCVideoRecordStopped = {0x2000E546}; |
54 const TUid KCamCControllerCCVideoFileComposed = {0x2000E547}; |
55 const TUid KCamCControllerCCVideoFileComposed = {0x2000E547}; |
55 |
56 |
56 // Custom command for setting a new filename without closing & reopening the controller |
|
57 enum TCamCControllerCustomCommands |
|
58 { |
|
59 ECamCControllerCCNewFilename = 0, |
|
60 ECamCControllerCCVideoStopAsync |
|
61 }; |
|
62 |
|
63 const TInt KOneSecond = 1000000; |
|
64 const int KMaintainAspectRatio = false; |
|
65 const TInt64 KMinRequiredSpaceVideo = 4000000; |
57 const TInt64 KMinRequiredSpaceVideo = 4000000; |
66 const uint KOneMillion = 1000000; |
|
67 const qreal KMetaDataCoeff = 1.03; // Coefficient to estimate metadata amount |
|
68 const uint KCamCMaxClipDurationInSecs = 5400; // Maximun video clip duration in seconds |
|
69 const qreal KCMRAvgVideoBitRateScaler = 0.9; // avg video bit rate scaler |
|
70 } |
58 } |
71 |
59 |
72 |
60 |
73 /*! |
61 /*! |
74 * CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian |
62 * CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian |
75 */ |
63 */ |
76 CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian( |
64 CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian( |
77 CxeCameraDevice &cameraDevice, |
65 CxeCameraDevice &cameraDevice, |
78 CxeViewfinderControl &viewfinderControl, |
66 CxeViewfinderControl &viewfinderControl, |
|
67 CxeSnapshotControl &snapshotControl, |
79 CxeCameraDeviceControl &cameraDeviceControl, |
68 CxeCameraDeviceControl &cameraDeviceControl, |
80 CxeFilenameGenerator &nameGenerator, |
69 CxeFilenameGenerator &nameGenerator, |
81 CxeSettings &settings, |
70 CxeSettings &settings, |
82 CxeQualityPresets &qualityPresets, |
71 CxeQualityPresets &qualityPresets, |
83 CxeDiskMonitor &diskMonitor) |
72 CxeDiskMonitor &diskMonitor) |
84 : CxeStateMachine("CxeVideoCaptureControlSymbian"), |
73 : CxeStateMachine("CxeVideoCaptureControlSymbian"), |
85 mVideoRecorder(NULL), |
74 mVideoRecorder(NULL), |
86 mCameraDevice(cameraDevice), |
75 mCameraDevice(cameraDevice), |
87 mCameraDeviceControl(cameraDeviceControl), |
76 mCameraDeviceControl(cameraDeviceControl), |
88 mViewfinderControl(viewfinderControl), |
77 mViewfinderControl(viewfinderControl), |
|
78 mSnapshotControl(snapshotControl), |
89 mFilenameGenerator(nameGenerator), |
79 mFilenameGenerator(nameGenerator), |
90 mSettings(settings), |
80 mSettings(settings), |
91 mQualityPresets(qualityPresets), |
81 mQualityPresets(qualityPresets), |
92 mDiskMonitor(diskMonitor), |
82 mDiskMonitor(diskMonitor), |
93 mSnapshot(), |
83 mSnapshot(), |
94 mNewFileName(""), |
84 mVideoStartSoundPlayer(NULL), |
|
85 mVideoStopSoundPlayer(NULL), |
95 mCurrentFilename("") |
86 mCurrentFilename("") |
96 { |
87 { |
97 CX_DEBUG_ENTER_FUNCTION(); |
88 CX_DEBUG_ENTER_FUNCTION(); |
98 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_IN, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 1"); |
89 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_IN, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 1"); |
99 |
90 |
116 this, SLOT(prepareForCameraDelete())); |
107 this, SLOT(prepareForCameraDelete())); |
117 connect(&cameraDevice, SIGNAL(prepareForRelease()), |
108 connect(&cameraDevice, SIGNAL(prepareForRelease()), |
118 this, SLOT(prepareForRelease()) ); |
109 this, SLOT(prepareForRelease()) ); |
119 connect(&cameraDevice, SIGNAL(cameraAllocated(CxeError::Id)), |
110 connect(&cameraDevice, SIGNAL(cameraAllocated(CxeError::Id)), |
120 this, SLOT(handleCameraAllocated(CxeError::Id))); |
111 this, SLOT(handleCameraAllocated(CxeError::Id))); |
|
112 |
121 // connect playing sound signals |
113 // connect playing sound signals |
122 connect(mVideoStartSoundPlayer, SIGNAL(playComplete(int)), |
114 connect(mVideoStartSoundPlayer, SIGNAL(playComplete(int)), |
123 this, SLOT(handleSoundPlayed())); |
115 this, SLOT(handleSoundPlayed())); |
124 |
116 |
|
117 // connect snapshot ready signal |
|
118 connect(&mSnapshotControl, SIGNAL(snapshotReady(CxeError::Id, const QPixmap&)), |
|
119 this, SLOT(handleSnapshotReady(CxeError::Id, const QPixmap&))); |
|
120 |
125 // enabling setting change callbacks to videocapturecontrol |
121 // enabling setting change callbacks to videocapturecontrol |
126 connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)), |
122 connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)), |
127 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
123 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
128 |
124 connect(&mSettings, SIGNAL(sceneChanged(CxeScene&)), |
129 connect(&mSettings, SIGNAL(sceneChanged(CxeScene&)), this, SLOT(handleSceneChanged(CxeScene&))); |
125 this, SLOT(handleSceneChanged(CxeScene&))); |
130 |
|
131 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_M2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
126 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_M2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
132 |
127 |
133 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 0"); |
128 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 0"); |
134 CX_DEBUG_EXIT_FUNCTION(); |
129 CX_DEBUG_EXIT_FUNCTION(); |
135 } |
130 } |
136 |
|
137 |
131 |
138 /*! |
132 /*! |
139 * CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
133 * CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
140 */ |
134 */ |
141 CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
135 CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
166 // video recorder already initalized. Continue to prepare video reocording. |
159 // video recorder already initalized. Continue to prepare video reocording. |
167 open(); |
160 open(); |
168 } |
161 } |
169 |
162 |
170 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 0" ); |
163 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 0" ); |
171 |
164 CX_DEBUG_EXIT_FUNCTION(); |
172 CX_DEBUG_EXIT_FUNCTION(); |
165 } |
173 } |
|
174 |
|
175 |
166 |
176 /* |
167 /* |
177 * Releases all resources |
168 * Releases all resources |
178 */ |
169 */ |
179 void CxeVideoCaptureControlSymbian::deinit() |
170 void CxeVideoCaptureControlSymbian::deinit() |
180 { |
171 { |
181 CX_DEBUG_ENTER_FUNCTION(); |
172 CX_DEBUG_ENTER_FUNCTION(); |
182 |
173 |
183 if(state() == Idle) { |
174 // Nothing to do if already idle. |
184 // nothing to do |
175 if(state() != Idle) { |
185 return; |
176 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" ); |
186 } |
177 |
187 |
178 // first stop viewfinder |
188 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" ); |
179 mViewfinderControl.stop(); |
189 |
180 |
190 // first stop viewfinder |
181 // stop video-recording in-case if its ongoing. |
191 mViewfinderControl.stop(); |
182 stop(); |
192 |
183 |
193 // stop video-recording in-case if its ongoing. |
184 mSnapshotControl.stop(); |
194 stop(); |
185 |
195 |
186 if (mVideoRecorder) { |
196 if (mCameraDevice.cameraSnapshot()) { |
187 mVideoRecorder->close(); |
197 mCameraDevice.cameraSnapshot()->StopSnapshot(); |
188 } |
198 } |
189 |
199 |
190 mCurrentFilename = QString(""); |
200 if (mVideoRecorder) { |
191 |
201 mVideoRecorder->Close(); |
192 setState(Idle); |
202 } |
193 |
203 |
194 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" ); |
204 // revert back the new filename to empty string so that we generate a new file name |
195 } |
205 // when we init again |
196 CX_DEBUG_EXIT_FUNCTION(); |
206 mNewFileName = QString(""); |
197 } |
207 |
|
208 setState(Idle); |
|
209 |
|
210 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" ); |
|
211 |
|
212 CX_DEBUG_EXIT_FUNCTION(); |
|
213 } |
|
214 |
|
215 |
198 |
216 /*! |
199 /*! |
217 * Intializes VideoRecorder for recording. |
200 * Intializes VideoRecorder for recording. |
218 */ |
201 */ |
219 void CxeVideoCaptureControlSymbian::initVideoRecorder() |
202 void CxeVideoCaptureControlSymbian::initVideoRecorder() |
220 { |
203 { |
221 CX_DEBUG_ENTER_FUNCTION(); |
204 CX_DEBUG_ENTER_FUNCTION(); |
222 |
205 |
223 if (state() != Idle) { |
206 // Init needed only in Idle state |
224 // not valid state to start "open" operation |
207 if (state() == Idle) { |
225 return; |
208 try { |
226 } |
209 // if video recorder is not created, do it now. |
227 |
210 createVideoRecorder(); |
228 if(!mVideoRecorder) { |
211 |
229 // if video recorder is not created, do it now. |
212 // update current video quality details from icm. |
230 createVideoRecorder(); |
213 // Throws an error if unable to get the quality. |
231 } |
214 getVideoQualityDetails(mCurrentVideoDetails); |
232 |
215 |
233 // update current video quality details from icm |
216 // Video recorder is ready to open video file for recording. |
234 CxeError::Id err = getVideoQualityDetails(mCurrentVideoDetails); |
|
235 |
|
236 if (!err) { |
|
237 // read videofile mime type |
|
238 QByteArray videoFileData = |
|
239 mCurrentVideoDetails.mVideoFileMimeType.toLatin1(); |
|
240 TPtrC8 videoFileMimeType(reinterpret_cast<const TUint8*> |
|
241 (videoFileData.constData()), videoFileData.size()); |
|
242 |
|
243 // read preferred supplier |
|
244 TPtrC16 supplier(reinterpret_cast<const TUint16*> |
|
245 (mCurrentVideoDetails.mPreferredSupplier.utf16())); |
|
246 |
|
247 err = findVideoController(videoFileMimeType, supplier); |
|
248 |
|
249 if (!err) { |
|
250 // video recorder is ready to open video file for recording. |
|
251 setState(Initialized); |
217 setState(Initialized); |
252 open(); |
218 open(); |
253 } |
219 } catch (const std::exception &e) { |
254 } else { |
220 // Handle error |
255 err = CxeErrorHandlingSymbian::map(KErrNotReady); |
221 handlePrepareFailed(); |
256 } |
222 } |
257 |
223 } |
258 if (err) { |
224 |
259 // In case of error |
225 CX_DEBUG_EXIT_FUNCTION(); |
260 emit videoPrepareComplete(err); |
226 } |
261 deinit(); |
|
262 } |
|
263 |
|
264 CX_DEBUG_EXIT_FUNCTION(); |
|
265 } |
|
266 |
|
267 |
|
268 |
227 |
269 /*! |
228 /*! |
270 * Opens file for video recording. |
229 * Opens file for video recording. |
271 */ |
230 */ |
272 void CxeVideoCaptureControlSymbian::open() |
231 void CxeVideoCaptureControlSymbian::open() |
273 { |
232 { |
274 CX_DEBUG_ENTER_FUNCTION(); |
233 CX_DEBUG_ENTER_FUNCTION(); |
275 |
234 |
276 if (state() != Initialized) { |
235 // Check valid state to start "open" operation |
277 // not valid state to start "open" operation |
236 if (state() == Initialized) { |
278 return; |
237 try { |
279 } |
238 // generate video file name, if necessary |
280 |
239 generateFilename(); |
281 CxeError::Id err = CxeError::None; |
240 CX_DEBUG(( "Next video file path: %s", mCurrentFilename.toAscii().constData() )); |
282 |
241 |
283 // generate video file name, if necessary |
242 // Start preparing.. |
284 if (mNewFileName.isEmpty()) { |
243 setState(CxeVideoCaptureControl::Preparing); |
285 QStringList list = mCurrentVideoDetails.mVideoFileMimeType.split("/"); |
244 |
286 QString fileExt("."); |
245 // Exception thrown if open fails. |
287 if (list.count() == 2) { |
246 mVideoRecorder->open(mCameraDevice.camera()->Handle(), |
288 fileExt = fileExt + list[1]; |
247 mCurrentFilename, |
289 } |
248 mCurrentVideoDetails.mVideoFileMimeType, |
290 // Generate new filename and open the file for writing video data |
249 mCurrentVideoDetails.mPreferredSupplier, |
291 err = mFilenameGenerator.generateFilename(mNewFileName, fileExt); |
250 mCurrentVideoDetails.mVideoCodecMimeType, |
292 if (err == CxeError::None) { |
251 mCurrentVideoDetails.mAudioType); |
293 mCurrentFilename = mNewFileName; |
252 } catch (const std::exception &e) { |
294 } else { |
253 handlePrepareFailed(); |
295 // file name is not valid, re-initialize the value of current string |
254 } |
296 // back to empty string |
255 } |
297 mCurrentFilename = QString(""); |
256 CX_DEBUG_EXIT_FUNCTION(); |
298 } |
257 } |
299 } |
258 |
300 |
259 /*! |
301 if (!err && |
260 * Helper method for generating filename. |
302 mVideoRecorder && |
261 * Throws exception, if file type mime is formatted wrong or |
303 !mCurrentFilename.isEmpty()) { |
262 * filename generation fails. |
304 |
263 */ |
305 TPtrC16 fName(reinterpret_cast<const TUint16*>(mCurrentFilename.utf16())); |
264 void CxeVideoCaptureControlSymbian::generateFilename() |
306 CX_DEBUG(( "Next video file path: %s", mCurrentFilename.toAscii().constData() )); |
265 { |
307 |
266 CX_DEBUG_ENTER_FUNCTION(); |
308 // read video codec mime type |
267 mCurrentFilename = QString(""); |
309 QByteArray videoCodecData = |
268 |
310 mCurrentVideoDetails.mVideoCodecMimeType.toLatin1(); |
269 QStringList list = mCurrentVideoDetails.mVideoFileMimeType.split("/"); |
311 TPtrC8 videoCodecMimeType(reinterpret_cast<const TUint8*> |
270 // Throw exception if mime string is formatted wrong. |
312 (videoCodecData.constData()), videoCodecData.size()); |
271 if (list.count() != 2) { |
313 |
272 throw new CxeException(CxeError::General); |
314 setState(CxeVideoCaptureControl::Preparing); |
273 } |
315 |
274 QString fileExt = "." + list[1]; |
316 TRAPD(openErr, mVideoRecorder->OpenFileL(fName, |
275 |
317 mCameraDevice.camera()->Handle(), |
276 // Generate new filename and open the file for writing video data |
318 mVideoControllerUid, |
277 CxeException::throwIfError(mFilenameGenerator.generateFilename(mCurrentFilename, fileExt)); |
319 mVideoFormatUid, |
278 |
320 videoCodecMimeType, |
279 CX_DEBUG_EXIT_FUNCTION(); |
321 audioType(mCurrentVideoDetails.mAudioType))); |
280 } |
322 |
|
323 err = CxeErrorHandlingSymbian::map(openErr); |
|
324 } |
|
325 if (err) { |
|
326 // error occured. |
|
327 deinit(); |
|
328 emit videoPrepareComplete(err); |
|
329 } |
|
330 CX_DEBUG_EXIT_FUNCTION(); |
|
331 } |
|
332 |
|
333 |
|
334 /*! |
|
335 * Prepare Video Recorder with necessary settings for video capture. |
|
336 */ |
|
337 TFourCC CxeVideoCaptureControlSymbian::audioType(const QString& str) |
|
338 { |
|
339 CX_DEBUG_ENTER_FUNCTION(); |
|
340 |
|
341 QByteArray audioType = str.toAscii(); |
|
342 |
|
343 quint8 char1(' '); |
|
344 quint8 char2(' '); |
|
345 quint8 char3(' '); |
|
346 quint8 char4(' '); |
|
347 |
|
348 if (audioType.count() > 3) { |
|
349 char1 = audioType[0]; |
|
350 char2 = audioType[1]; |
|
351 char3 = audioType[2]; |
|
352 |
|
353 if (audioType.count() == 4) { |
|
354 char4 = audioType[3]; |
|
355 } |
|
356 } |
|
357 |
|
358 return TFourCC(char1, char2, char3, char4); |
|
359 } |
|
360 |
|
361 |
281 |
362 /*! |
282 /*! |
363 * Prepare Video Recorder with necessary settings for video capture. |
283 * Prepare Video Recorder with necessary settings for video capture. |
364 */ |
284 */ |
365 void CxeVideoCaptureControlSymbian::prepare() |
285 void CxeVideoCaptureControlSymbian::prepare() |
388 mSettings.get(CxeSettingIds::FRAME_RATE, frameRate); |
303 mSettings.get(CxeSettingIds::FRAME_RATE, frameRate); |
389 if (frameRate <= 0) { |
304 if (frameRate <= 0) { |
390 frameRate = mCurrentVideoDetails.mVideoFrameRate; |
305 frameRate = mCurrentVideoDetails.mVideoFrameRate; |
391 } |
306 } |
392 |
307 |
|
308 CX_DEBUG(("Video resolution (%d,%d)", mCurrentVideoDetails.mWidth, |
|
309 mCurrentVideoDetails.mHeight)); |
|
310 CX_DEBUG(("Video bitrate = %d)", mCurrentVideoDetails.mVideoBitRate)); |
393 CX_DEBUG(("Video frame rate = %d)", frameRate)); |
311 CX_DEBUG(("Video frame rate = %d)", frameRate)); |
394 |
312 |
395 TRAPD(err, |
313 try { |
396 { |
314 mVideoRecorder->setVideoFrameSize(frameSize); |
397 mVideoRecorder->SetVideoFrameSizeL(frameSize); |
315 mVideoRecorder->setVideoFrameRate(frameRate); |
398 mVideoRecorder->SetVideoFrameRateL(frameRate); |
316 mVideoRecorder->setVideoBitRate(mCurrentVideoDetails.mVideoBitRate); |
399 mVideoRecorder->SetVideoBitRateL(mCurrentVideoDetails.mVideoBitRate); |
317 mVideoRecorder->setAudioEnabled(muteSetting == 0); |
400 mVideoRecorder->SetAudioEnabledL(muteSetting == 0); |
318 // "No limit" value is handled in video recorder wrapper. |
401 // "No limit" value is handled in video recorder wrapper. |
319 mVideoRecorder->setVideoMaxSize(mCurrentVideoDetails.mMaximumSizeInBytes); |
402 mVideoRecorder->SetMaxClipSizeL(mCurrentVideoDetails.mMaximumSizeInBytes); |
320 |
403 } |
321 // Settings have been applied successfully, start to prepare. |
404 ); |
322 mVideoRecorder->prepare(); |
405 |
323 |
406 if (!err) { |
324 // Prepare snapshot. Snapshot control throws error if problems. |
407 // settings have been applied successfully, start to prepare |
325 QSize snapshotSize = mSnapshotControl.calculateSnapshotSize( |
408 mVideoRecorder->Prepare(); |
326 mViewfinderControl.deviceDisplayResolution(), |
409 // prepare snapshot |
327 QSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight)); |
410 err = prepareVideoSnapshot(); |
328 mSnapshotControl.start(snapshotSize); |
411 } |
329 |
412 |
330 // Prepare zoom only when there are no errors during prepare. |
413 if (!err) { |
|
414 // prepare zoom only when there are no errors during prepare. |
|
415 emit prepareZoomForVideo(); |
331 emit prepareZoomForVideo(); |
416 } |
332 emit videoPrepareComplete(CxeError::None); |
417 // emit video prepare status |
333 } catch (const std::exception &e) { |
418 emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err)); |
334 // Handle error. |
|
335 handlePrepareFailed(); |
|
336 } |
419 |
337 |
420 OstTrace0(camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_VIDCAPCONT_PREPARE 0"); |
338 OstTrace0(camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_VIDCAPCONT_PREPARE 0"); |
421 |
339 CX_DEBUG_EXIT_FUNCTION(); |
422 CX_DEBUG_EXIT_FUNCTION(); |
340 } |
423 } |
341 |
424 |
342 /*! |
425 |
343 * Fetches video qualites details based on video quality setting. |
426 |
344 */ |
427 /*! |
345 void |
428 Fetches video qualites details based on video quality setting. |
|
429 Returns CxeError codes if any. |
|
430 */ |
|
431 CxeError::Id |
|
432 CxeVideoCaptureControlSymbian::getVideoQualityDetails(CxeVideoDetails &videoInfo) |
346 CxeVideoCaptureControlSymbian::getVideoQualityDetails(CxeVideoDetails &videoInfo) |
433 { |
347 { |
434 CX_DEBUG_ENTER_FUNCTION(); |
348 CX_DEBUG_ENTER_FUNCTION(); |
435 |
349 |
436 int videoQuality = 0; |
350 int quality(0); |
437 CxeError::Id err = CxeError::None; |
351 |
438 |
352 // Get quality index for primary camera. Only one quality for secondary camera. |
439 if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { |
353 if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { |
440 err = mSettings.get(CxeSettingIds::VIDEO_QUALITY, videoQuality); |
354 CxeException::throwIfError(mSettings.get(CxeSettingIds::VIDEO_QUALITY, quality)); |
441 |
355 } |
442 bool validQuality = (videoQuality >= 0 && |
356 |
443 videoQuality < mIcmSupportedVideoResolutions.count()); |
357 if (quality < 0 || quality >= mIcmSupportedVideoResolutions.count()) { |
444 if (err == CxeError::None && validQuality) { |
358 throw new CxeException(CxeError::NotFound); |
445 // get video quality details |
359 } |
446 videoInfo = mIcmSupportedVideoResolutions.at(videoQuality); |
360 |
447 } else { |
361 // get video quality details |
448 // not valid video quality |
362 videoInfo = mIcmSupportedVideoResolutions.at(quality); |
449 err = CxeError::NotFound; |
363 |
450 } |
364 CX_DEBUG_EXIT_FUNCTION(); |
451 } else { |
365 } |
452 // get secondary camera video quality index |
|
453 if (mIcmSupportedVideoResolutions.count() > 0) { |
|
454 videoInfo = mIcmSupportedVideoResolutions.at(videoQuality); |
|
455 } else { |
|
456 // not valid video quality |
|
457 err = CxeError::NotFound; |
|
458 } |
|
459 } |
|
460 |
|
461 CX_DEBUG_EXIT_FUNCTION(); |
|
462 |
|
463 return err; |
|
464 } |
|
465 |
|
466 |
|
467 /**! |
|
468 Prepare snapshot |
|
469 Returns symbian error code. |
|
470 */ |
|
471 int CxeVideoCaptureControlSymbian::prepareVideoSnapshot() |
|
472 { |
|
473 CX_DEBUG_ENTER_FUNCTION(); |
|
474 |
|
475 CCamera::CCameraSnapshot *cameraSnapshot = mCameraDevice.cameraSnapshot(); |
|
476 CX_ASSERT_ALWAYS(cameraSnapshot); |
|
477 |
|
478 int err = KErrNone; |
|
479 // Whether or not we have postcapture on, we need the snapshot for Thumbnail Manager. |
|
480 if (cameraSnapshot) { |
|
481 // Cancel active snapshot |
|
482 cameraSnapshot->StopSnapshot(); |
|
483 |
|
484 // Prepare snapshot |
|
485 CCamera::TFormat snapFormat = CCamera::EFormatFbsBitmapColor16MU; |
|
486 TRAP(err, cameraSnapshot->PrepareSnapshotL(snapFormat, |
|
487 getSnapshotSize(), |
|
488 KMaintainAspectRatio)); |
|
489 CX_DEBUG(("PrepareSnapshotL done, err=%d", err)); |
|
490 // Start snapshot if no errors encountered. |
|
491 if (err == KErrNone) { |
|
492 CX_DEBUG(("Start video snapshot")); |
|
493 cameraSnapshot->StartSnapshot(); |
|
494 } |
|
495 } else { |
|
496 // No snapshot interface available. Report error. |
|
497 // Assert above takes care of this, but keeping this as an option. |
|
498 err = KErrNotReady; |
|
499 } |
|
500 |
|
501 CX_DEBUG_EXIT_FUNCTION(); |
|
502 |
|
503 return err; |
|
504 } |
|
505 |
|
506 |
|
507 |
|
508 /*! |
|
509 * Returns snapshot size. Snapshot size is calculated based on the |
|
510 * display resolution and current video aspect ratio. |
|
511 */ |
|
512 TSize CxeVideoCaptureControlSymbian::getSnapshotSize() const |
|
513 { |
|
514 CX_DEBUG_ENTER_FUNCTION(); |
|
515 |
|
516 TSize snapshotSize; |
|
517 |
|
518 QSize deviceResolution = mViewfinderControl.deviceDisplayResolution(); |
|
519 QSize size = QSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight); |
|
520 |
|
521 // scale according to aspect ratio. |
|
522 size.scale(deviceResolution.width(), |
|
523 deviceResolution.height(), |
|
524 Qt::KeepAspectRatio); |
|
525 CX_DEBUG(("Video Snapshot size, (%d,%d)", size.width(), size.height())); |
|
526 snapshotSize.SetSize(size.width(), deviceResolution.height()); |
|
527 |
|
528 CX_DEBUG_EXIT_FUNCTION(); |
|
529 |
|
530 return snapshotSize; |
|
531 } |
|
532 |
|
533 |
|
534 |
|
535 /**! |
|
536 * Camera events coming from ecam. |
|
537 */ |
|
538 void CxeVideoCaptureControlSymbian::handleCameraEvent(int eventUid, int error) |
|
539 { |
|
540 CX_DEBUG_ENTER_FUNCTION(); |
|
541 if (eventUid == KUidECamEventSnapshotUidValue) { |
|
542 handleSnapshotEvent(CxeErrorHandlingSymbian::map(error)); |
|
543 } |
|
544 CX_DEBUG_EXIT_FUNCTION(); |
|
545 } |
|
546 |
|
547 |
|
548 /*! |
|
549 * Handle Snapshot event from ecam |
|
550 */ |
|
551 void CxeVideoCaptureControlSymbian::handleSnapshotEvent(CxeError::Id error) |
|
552 { |
|
553 CX_DEBUG_ENTER_FUNCTION(); |
|
554 |
|
555 if (state() == Idle) { |
|
556 // we ignore this event, when we are not in active state(s) |
|
557 CX_DEBUG(( "wrong state, ignoring snapshot" )); |
|
558 CX_DEBUG_EXIT_FUNCTION(); |
|
559 return; |
|
560 } |
|
561 |
|
562 if (error) { |
|
563 mSnapshot = QPixmap(); |
|
564 emit snapshotReady(error, mSnapshot, filename()); |
|
565 return; |
|
566 } |
|
567 |
|
568 RArray<TInt> snapList; |
|
569 MCameraBuffer* buffer(NULL); |
|
570 // Note: Cleanup not required in this function |
|
571 CFbsBitmap *snapshot = NULL; |
|
572 TRAPD(snapErr, |
|
573 buffer = &mCameraDevice.cameraSnapshot()->SnapshotDataL(snapList)); |
|
574 if (!snapErr) { |
|
575 TInt firstImageIndex = snapList.Find(0); |
|
576 snapList.Close(); |
|
577 TRAP(snapErr, snapshot = &(buffer->BitmapL(firstImageIndex))); |
|
578 } |
|
579 if (!snapErr) { |
|
580 TSize size = snapshot->SizeInPixels(); |
|
581 TInt sizeInWords = size.iHeight * CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU) |
|
582 / sizeof(TUint32); |
|
583 |
|
584 TUint32 *snapshotData = NULL; |
|
585 snapshotData = new TUint32[sizeInWords]; |
|
586 |
|
587 if (snapshotData) { |
|
588 // Convert to QImage |
|
589 snapshot->LockHeap(); |
|
590 TUint32* dataPtr = snapshot->DataAddress(); |
|
591 memcpy(snapshotData, dataPtr, sizeof(TUint32) * sizeInWords); |
|
592 snapshot->UnlockHeap(); |
|
593 |
|
594 |
|
595 QImage *img = new QImage((uchar*) snapshotData, size.iWidth, size.iHeight, |
|
596 CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU), |
|
597 QImage::Format_RGB32); |
|
598 |
|
599 mSnapshot = QPixmap::fromImage(*img); |
|
600 delete [] snapshotData; |
|
601 delete img; |
|
602 } |
|
603 } |
|
604 if (buffer) { |
|
605 buffer->Release(); |
|
606 } |
|
607 // Snapshot ready |
|
608 emit snapshotReady(CxeErrorHandlingSymbian::map(snapErr), mSnapshot, filename()); |
|
609 |
|
610 CX_DEBUG_EXIT_FUNCTION(); |
|
611 } |
|
612 |
|
613 |
366 |
614 /*! |
367 /*! |
615 * Resets the video snapshot and current video filename |
368 * Resets the video snapshot and current video filename |
616 */ |
369 */ |
617 void CxeVideoCaptureControlSymbian::reset() |
370 void CxeVideoCaptureControlSymbian::reset() |
699 |
442 |
700 if (state() == Recording || state() == Paused) { |
443 if (state() == Recording || state() == Paused) { |
701 // first stop viewfinder |
444 // first stop viewfinder |
702 mViewfinderControl.stop(); |
445 mViewfinderControl.stop(); |
703 |
446 |
704 TInt asyncStopErr = mVideoRecorder->CustomCommandSync( |
447 try { |
705 TMMFMessageDestination(KCamCControllerImplementationUid, |
448 // Try asynchronous stopping first. |
706 KMMFObjectHandleController), |
449 mVideoRecorder->stop(true); |
707 ECamCControllerCCVideoStopAsync, |
450 // No error from asynchronous stop -> wait for stop event |
708 KNullDesC8, |
451 setState(Stopping); |
709 KNullDesC8 ); |
452 } catch (const std::exception &e) { |
710 CX_DEBUG(("ECamCControllerCCVideoStopAsync sent, err=%d", asyncStopErr)); |
453 CX_DEBUG(("CxeVideoCaptureControlSymbian - async stop failed, try sync..")); |
711 if (asyncStopErr) { // fall back to synchronous stop |
454 try { |
712 TInt syncStopErr = mVideoRecorder->Stop(); |
455 mVideoRecorder->stop(false); |
713 if (syncStopErr) { |
456 // stop operation went fine, set back the state to Initialized. |
714 // error during stop operation, release resources |
|
715 emit videoComposed(CxeErrorHandlingSymbian::map(asyncStopErr), filename()); |
|
716 deinit(); |
|
717 } else { |
|
718 // stop operation went fine, set back the state to Initialized. |
|
719 setState(Initialized); |
457 setState(Initialized); |
|
458 // must increment counter now since no callback is coming in sync stop |
720 mFilenameGenerator.raiseCounterValue(); |
459 mFilenameGenerator.raiseCounterValue(); |
|
460 } catch (const std::exception &e) { |
|
461 // Even synchronous stopping failed -> release resources. |
|
462 CX_DEBUG(("CxeVideoCaptureControlSymbian - sync stop failed, too!")); |
|
463 handleComposeFailed(qt_symbian_exception2Error(e)); |
721 } |
464 } |
|
465 } |
|
466 } |
|
467 |
|
468 CX_DEBUG_EXIT_FUNCTION(); |
|
469 } |
|
470 |
|
471 /*! |
|
472 * Callback when "Open" operation is complete. |
|
473 */ |
|
474 void CxeVideoCaptureControlSymbian::MvruoOpenComplete(TInt aError) |
|
475 { |
|
476 CX_DEBUG_ENTER_FUNCTION(); |
|
477 CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoOpenComplete, err=%d", aError)); |
|
478 |
|
479 if (state() == Preparing) { |
|
480 if (!aError) { |
|
481 prepare(); |
722 } else { |
482 } else { |
723 // No error from asynch stop custom command... wait for stop event |
483 handlePrepareFailed(); |
724 setState(Stopping); |
484 } |
725 mFilenameGenerator.raiseCounterValue(); |
485 } |
726 } |
486 |
727 } |
487 CX_DEBUG_EXIT_FUNCTION(); |
728 |
488 } |
729 CX_DEBUG_EXIT_FUNCTION(); |
|
730 } |
|
731 |
|
732 |
|
733 /*! |
|
734 * Callback when "Open" operation is complete. |
|
735 */ |
|
736 void CxeVideoCaptureControlSymbian::MvruoOpenComplete(TInt aError) |
|
737 { |
|
738 CX_DEBUG_ENTER_FUNCTION(); |
|
739 CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoOpenComplete, err=%d", aError)); |
|
740 |
|
741 if (state() == Preparing) { |
|
742 if (aError != KErrNone) { |
|
743 deinit(); |
|
744 CxeError::Id err = CxeErrorHandlingSymbian::map(KErrNotReady); |
|
745 // report error to interested parties |
|
746 emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err)); |
|
747 } else { |
|
748 prepare(); |
|
749 } |
|
750 } |
|
751 |
|
752 CX_DEBUG_EXIT_FUNCTION(); |
|
753 } |
|
754 |
|
755 |
489 |
756 /*! |
490 /*! |
757 * Callback when "Prepare" request is complete. |
491 * Callback when "Prepare" request is complete. |
758 */ |
492 */ |
759 void CxeVideoCaptureControlSymbian::MvruoPrepareComplete(TInt aError) |
493 void CxeVideoCaptureControlSymbian::MvruoPrepareComplete(TInt aError) |
822 CX_DEBUG(("KCamCControllerCCVideoFileComposed")); |
550 CX_DEBUG(("KCamCControllerCCVideoFileComposed")); |
823 if (state() == Stopping) { |
551 if (state() == Stopping) { |
824 // stop operation went fine, set back the state to intialized. |
552 // stop operation went fine, set back the state to intialized. |
825 setState(Initialized); |
553 setState(Initialized); |
826 } |
554 } |
|
555 mFilenameGenerator.raiseCounterValue(); |
827 // video file has composed, everything went well, inform the client |
556 // video file has composed, everything went well, inform the client |
828 emit videoComposed(CxeError::None, filename()); |
557 emit videoComposed(CxeError::None, filename()); |
829 // revert back the new filename to empty string, since recording |
|
830 // is complete and we need to generate a new file name |
|
831 mNewFileName = QString(""); |
|
832 } else { |
558 } else { |
833 CX_DEBUG(("ignoring unknown MvruoEvent 0x%08x", aEvent.iEventType.iUid )); |
559 CX_DEBUG(("ignoring unknown MvruoEvent 0x%08x", aEvent.iEventType.iUid )); |
834 } |
560 } |
835 |
561 |
836 CX_DEBUG_EXIT_FUNCTION(); |
562 CX_DEBUG_EXIT_FUNCTION(); |
837 } |
563 } |
838 |
564 |
839 |
|
840 /*! |
|
841 Get corresponding controller for video capture. |
|
842 @param aMimeType denotes videofile mimetype, |
|
843 @param aPreferredSupplier denotes supplier. |
|
844 Returns CxeError::Id if any. |
|
845 */ |
|
846 CxeError::Id |
|
847 CxeVideoCaptureControlSymbian::findVideoController(const TDesC8& aMimeType, |
|
848 const TDesC& aSupplier) |
|
849 { |
|
850 CX_DEBUG_ENTER_FUNCTION(); |
|
851 |
|
852 CX_DEBUG(("video file mime type : %s", &aMimeType)); |
|
853 CX_DEBUG(("supplier name: %s", &aSupplier)); |
|
854 |
|
855 mVideoControllerUid.iUid = 0; |
|
856 mVideoFormatUid.iUid = 0; |
|
857 |
|
858 // Retrieve a list of possible controllers from ECOM. |
|
859 // Controller must support recording the requested mime type. |
|
860 // Controller must be provided by preferred supplier. |
|
861 |
|
862 CMMFControllerPluginSelectionParameters* cSelect(NULL); |
|
863 CMMFFormatSelectionParameters* fSelect(NULL); |
|
864 RMMFControllerImplInfoArray controllers; |
|
865 |
|
866 TRAPD(err, cSelect = CMMFControllerPluginSelectionParameters::NewL()); |
|
867 if (err) { |
|
868 return CxeErrorHandlingSymbian::map(err); |
|
869 } |
|
870 |
|
871 TRAP(err, fSelect = CMMFFormatSelectionParameters::NewL()); |
|
872 if (err) { |
|
873 if(cSelect) { |
|
874 delete cSelect; |
|
875 } |
|
876 return CxeErrorHandlingSymbian::map(err); |
|
877 } |
|
878 |
|
879 TRAP( err, { |
|
880 fSelect->SetMatchToMimeTypeL(aMimeType); |
|
881 cSelect->SetRequiredRecordFormatSupportL(*fSelect); |
|
882 cSelect->SetPreferredSupplierL(aSupplier, |
|
883 CMMFPluginSelectionParameters::EOnlyPreferredSupplierPluginsReturned); |
|
884 cSelect->ListImplementationsL(controllers); |
|
885 } ); |
|
886 |
|
887 if (!err && controllers.Count() >= 1) { |
|
888 // KErrNotFound is returned unless a controller is found |
|
889 err = KErrNotFound; |
|
890 // Get the controller UID. |
|
891 mVideoControllerUid = controllers[0]->Uid(); |
|
892 |
|
893 // Inquires the controller about supported formats. |
|
894 // We use the first controller found having index 0. |
|
895 RMMFFormatImplInfoArray formats; |
|
896 formats = controllers[0]->RecordFormats(); |
|
897 |
|
898 // Get the first format that supports our mime type. |
|
899 int count = formats.Count(); |
|
900 for (int i=0; i<count; i++) { |
|
901 if (formats[i]->SupportsMimeType(aMimeType)) { |
|
902 mVideoFormatUid = formats[i]->Uid(); // set the UID |
|
903 err = KErrNone; |
|
904 break; |
|
905 } |
|
906 } |
|
907 } |
|
908 delete cSelect; |
|
909 delete fSelect; |
|
910 controllers.ResetAndDestroy(); |
|
911 |
|
912 CX_DEBUG_EXIT_FUNCTION(); |
|
913 |
|
914 return CxeErrorHandlingSymbian::map(err); |
|
915 } |
|
916 |
|
917 |
|
918 /*! |
565 /*! |
919 * camera reference changing, release resources |
566 * camera reference changing, release resources |
920 */ |
567 */ |
921 void CxeVideoCaptureControlSymbian::prepareForCameraDelete() |
568 void CxeVideoCaptureControlSymbian::prepareForCameraDelete() |
922 { |
569 { |
933 CX_DEBUG_ENTER_FUNCTION(); |
580 CX_DEBUG_ENTER_FUNCTION(); |
934 deinit(); |
581 deinit(); |
935 CX_DEBUG_EXIT_FUNCTION(); |
582 CX_DEBUG_EXIT_FUNCTION(); |
936 } |
583 } |
937 |
584 |
938 |
585 /*! |
939 /*! |
586 * new camera available |
940 * new camera available, |
|
941 */ |
587 */ |
942 void CxeVideoCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) |
588 void CxeVideoCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) |
943 { |
589 { |
944 CX_DEBUG_ENTER_FUNCTION(); |
590 CX_DEBUG_ENTER_FUNCTION(); |
945 |
591 |
946 if (!error) { |
592 if (!error) { |
947 // initialize the video recorder utility |
593 try { |
948 createVideoRecorder(); |
594 // Create the video recorder utility |
|
595 createVideoRecorder(); |
|
596 } catch (...) { |
|
597 // We are just trying to create the recorder early. |
|
598 // Retry later when preparing, and fail then if |
|
599 // error still persists. |
|
600 } |
949 // new camera available, read supported video qualities from icm |
601 // new camera available, read supported video qualities from icm |
950 // load all still qualities supported by icm |
602 // load all video qualities supported by icm |
951 mIcmSupportedVideoResolutions.clear(); |
603 mIcmSupportedVideoResolutions.clear(); |
952 Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex(); |
604 Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex(); |
953 // get list of supported image qualities based on camera index |
605 // get list of supported image qualities based on camera index |
954 mIcmSupportedVideoResolutions = |
606 mIcmSupportedVideoResolutions = |
955 mQualityPresets.videoQualityPresets(cameraIndex); |
607 mQualityPresets.videoQualityPresets(cameraIndex); |
956 } |
608 } |
957 |
609 |
958 CX_DEBUG_EXIT_FUNCTION(); |
610 CX_DEBUG_EXIT_FUNCTION(); |
959 } |
611 } |
960 |
612 |
961 |
|
962 /*! |
613 /*! |
963 * Initializes video recorder. |
614 * Initializes video recorder. |
|
615 * May throw exception. |
964 */ |
616 */ |
965 void CxeVideoCaptureControlSymbian::createVideoRecorder() |
617 void CxeVideoCaptureControlSymbian::createVideoRecorder() |
966 { |
618 { |
967 CX_DEBUG_ENTER_FUNCTION(); |
619 CX_DEBUG_ENTER_FUNCTION(); |
968 |
620 if (mVideoRecorder == NULL) { |
969 // init video recoder |
621 mVideoRecorder = new CxeVideoRecorderUtilitySymbian(*this); |
970 if (state() == CxeVideoCaptureControl::Idle) { |
622 } |
971 if (mVideoRecorder == NULL) { |
623 CX_DEBUG_EXIT_FUNCTION(); |
972 TRAPD(initErr, mVideoRecorder = |
624 } |
973 new CxeVideoRecorderUtilitySymbian( *this , |
625 |
974 KAudioPriorityVideoRecording, |
626 /*! |
975 TMdaPriorityPreference( KAudioPrefVideoRecording ))); |
627 * releases resources used by video capture control |
976 if (initErr) { |
|
977 CX_DEBUG(("WARNING - VideoRecorderUtility could not be reserved. Failed with err:%d", initErr)); |
|
978 mVideoRecorder = NULL; |
|
979 } |
|
980 } |
|
981 } |
|
982 |
|
983 CX_DEBUG_EXIT_FUNCTION(); |
|
984 } |
|
985 |
|
986 |
|
987 /*! |
|
988 * releases resources used by videocapture |
|
989 */ |
628 */ |
990 void CxeVideoCaptureControlSymbian::releaseResources() |
629 void CxeVideoCaptureControlSymbian::releaseResources() |
991 { |
630 { |
992 CX_DEBUG_ENTER_FUNCTION(); |
631 CX_DEBUG_ENTER_FUNCTION(); |
993 |
632 |
1091 { |
726 { |
1092 CX_DEBUG_ENTER_FUNCTION(); |
727 CX_DEBUG_ENTER_FUNCTION(); |
1093 |
728 |
1094 if (state() == CxeVideoCaptureControl::Recording || |
729 if (state() == CxeVideoCaptureControl::Recording || |
1095 state() == CxeVideoCaptureControl::Paused) { |
730 state() == CxeVideoCaptureControl::Paused) { |
1096 TTimeIntervalMicroSeconds remaining = 0; |
731 time = mVideoRecorder->availableRecordingTime(); |
1097 remaining = mVideoRecorder->RecordTimeAvailable(); |
732 CX_DEBUG(("CxeVideoCaptureControlSymbian - time remaining: %d", time)); |
1098 time = remaining.Int64() * 1.0 / KOneSecond; |
|
1099 CX_DEBUG(( "timeRemaining2: %d", time )); |
|
1100 } else { |
733 } else { |
1101 // Check if we need to recalculate the remaining time. |
734 // Check if we need to recalculate the remaining time. |
1102 if (mCurrentVideoDetails.mRemainingTime == CxeVideoDetails::UNKNOWN) { |
735 if (mCurrentVideoDetails.mRemainingTime == CxeVideoDetails::UNKNOWN) { |
1103 calculateRemainingTime(mCurrentVideoDetails, mCurrentVideoDetails.mRemainingTime); |
736 mCurrentVideoDetails.mRemainingTime = calculateRemainingTime(mCurrentVideoDetails); |
1104 } |
737 } |
1105 time = mCurrentVideoDetails.mRemainingTime; |
738 time = mCurrentVideoDetails.mRemainingTime; |
1106 } |
739 } |
1107 |
740 |
1108 CX_DEBUG_EXIT_FUNCTION(); |
741 CX_DEBUG_EXIT_FUNCTION(); |
1109 } |
742 } |
1110 |
743 |
1111 |
744 /*! |
1112 |
745 * Get the remaining recording time |
1113 /*! |
746 * @param videoDetails Contains the current video resolution that is in use. |
1114 * algorithm to calculate remaining recording time |
747 * @return The remaining recording time |
1115 @ param videoDetails contains the current video resolution that is in use. |
748 */ |
1116 @ time contains the remaining recording time |
749 int CxeVideoCaptureControlSymbian::calculateRemainingTime(const CxeVideoDetails& videoDetails) |
1117 */ |
750 { |
1118 void CxeVideoCaptureControlSymbian::calculateRemainingTime(CxeVideoDetails videoDetails, int &time) |
751 CX_DEBUG_ENTER_FUNCTION(); |
1119 { |
752 qint64 availableSpace = mDiskMonitor.free() - KMinRequiredSpaceVideo; |
1120 CX_DEBUG_ENTER_FUNCTION(); |
753 int time = mQualityPresets.recordingTimeAvailable(videoDetails, availableSpace); |
1121 |
754 CX_DEBUG_EXIT_FUNCTION(); |
1122 TTimeIntervalMicroSeconds remaining = 0; |
755 return time; |
1123 |
756 } |
1124 // get available space in the drive selected in the settings |
757 |
1125 // for storing videos |
758 /*! |
1126 qint64 availableSpace = mDiskMonitor.free(); |
759 * Calculates elapsed recording time during video recording |
1127 |
760 * @return Did fetching elapsed time succeed. |
1128 availableSpace = availableSpace - KMinRequiredSpaceVideo; |
|
1129 |
|
1130 // Maximum clip size may be limited for mms quality. |
|
1131 // If mMaximumSizeInBytes == 0, no limit is specified. |
|
1132 if (videoDetails.mMaximumSizeInBytes > 0 && videoDetails.mMaximumSizeInBytes < availableSpace) { |
|
1133 availableSpace = videoDetails.mMaximumSizeInBytes; |
|
1134 } |
|
1135 |
|
1136 // Use average audio/video bitrates to estimate remaining time |
|
1137 quint32 averageBitRate = 0; |
|
1138 quint32 averageByteRate = 0; |
|
1139 qreal scaler = mQualityPresets.avgVideoBitRateScaler(); |
|
1140 |
|
1141 if (scaler == 0) { |
|
1142 // video bit rate scaler is 0, use the constant value |
|
1143 scaler = KCMRAvgVideoBitRateScaler; |
|
1144 } |
|
1145 |
|
1146 int avgVideoBitRate = (videoDetails.mVideoBitRate * scaler); |
|
1147 int avgAudioBitRate = videoDetails.mAudioBitRate; |
|
1148 |
|
1149 int muteSetting = 0; // audio enabled |
|
1150 mSettings.get(CxeSettingIds::VIDEO_MUTE_SETTING, muteSetting); |
|
1151 |
|
1152 if (muteSetting == 1) { |
|
1153 // audio disabled from setting. hence no audio |
|
1154 avgAudioBitRate = 0; |
|
1155 } |
|
1156 |
|
1157 averageBitRate = (quint32)( |
|
1158 (avgVideoBitRate + avgAudioBitRate) * KMetaDataCoeff); |
|
1159 |
|
1160 averageByteRate = averageBitRate / 8; |
|
1161 |
|
1162 if (availableSpace <= 0) { |
|
1163 remaining = 0; |
|
1164 } else { |
|
1165 // converting microseconds to seconds |
|
1166 remaining = availableSpace * KOneMillion / averageByteRate; |
|
1167 if ( (remaining.Int64()) > (quint64(KCamCMaxClipDurationInSecs) * KOneMillion) ) { |
|
1168 remaining = (quint64(KCamCMaxClipDurationInSecs) * KOneMillion); |
|
1169 } |
|
1170 } |
|
1171 if ( remaining <= quint64(0) ) { |
|
1172 remaining = 0; |
|
1173 } |
|
1174 |
|
1175 time = remaining.Int64() * 1.0 / KOneSecond; |
|
1176 |
|
1177 CX_DEBUG(( "remaining time from algorithm: %d", time )); |
|
1178 |
|
1179 CX_DEBUG_EXIT_FUNCTION(); |
|
1180 } |
|
1181 |
|
1182 |
|
1183 /*! |
|
1184 * Calculates remaining recording time during video recording |
|
1185 */ |
761 */ |
1186 bool CxeVideoCaptureControlSymbian::elapsedTime(int &time) |
762 bool CxeVideoCaptureControlSymbian::elapsedTime(int &time) |
1187 { |
763 { |
1188 CX_DEBUG_ENTER_FUNCTION(); |
764 CX_DEBUG_ENTER_FUNCTION(); |
1189 |
765 |
1190 TTimeIntervalMicroSeconds timeElapsed = 0; |
|
1191 bool ok = false; |
766 bool ok = false; |
1192 if (state() == CxeVideoCaptureControl::Recording || |
767 if (state() == CxeVideoCaptureControl::Recording || |
1193 state() == CxeVideoCaptureControl::Paused) { |
768 state() == CxeVideoCaptureControl::Paused) { |
1194 TRAPD( err, timeElapsed = mVideoRecorder->DurationL() ); |
769 try { |
1195 if (!err) { |
770 time = mVideoRecorder->duration(); |
1196 time = timeElapsed.Int64() * 1.0 / KOneSecond; |
771 CX_DEBUG(("CxeVideoCaptureControlSymbian - elapsed: %d", time)); |
1197 CX_DEBUG(("timeElapsed2: %d", time)); |
|
1198 ok = true; |
772 ok = true; |
1199 } |
773 } catch (const std::exception &e) { |
1200 } |
774 // Returning false. |
1201 |
775 } |
1202 CX_DEBUG_EXIT_FUNCTION(); |
776 } |
1203 |
777 |
|
778 CX_DEBUG_EXIT_FUNCTION(); |
1204 return ok; |
779 return ok; |
1205 } |
780 } |
1206 |
781 |
1207 /*! |
782 /*! |
1208 * slot called when playing a sound has finished. |
783 * slot called when playing a sound has finished. |
1212 CX_DEBUG_ENTER_FUNCTION(); |
787 CX_DEBUG_ENTER_FUNCTION(); |
1213 |
788 |
1214 // start recording, if we were playing capture sound |
789 // start recording, if we were playing capture sound |
1215 if (state() == CxeVideoCaptureControl::PlayingStartSound) { |
790 if (state() == CxeVideoCaptureControl::PlayingStartSound) { |
1216 setState(CxeVideoCaptureControl::Recording); |
791 setState(CxeVideoCaptureControl::Recording); |
1217 |
792 mVideoRecorder->record(); |
1218 mVideoRecorder->Record(); |
|
1219 } |
793 } |
1220 |
794 |
1221 // in case of video capture stop sound playing, nothing needs to be done |
795 // in case of video capture stop sound playing, nothing needs to be done |
1222 // meaning the state set elsewhere, and the video capture has been stopped already |
796 // meaning the state set elsewhere, and the video capture has been stopped already |
1223 |
797 |
1224 CX_DEBUG_EXIT_FUNCTION(); |
798 CX_DEBUG_EXIT_FUNCTION(); |
1225 } |
799 } |
1226 |
800 |
|
801 /*! |
|
802 * Handle new snapshot. |
|
803 * @param status Status code for getting the snapshot. |
|
804 * @param snapshot Snapshot pixmap. Empty if error code reported. |
|
805 */ |
|
806 void CxeVideoCaptureControlSymbian::handleSnapshotReady(CxeError::Id status, const QPixmap& snapshot) |
|
807 { |
|
808 CX_DEBUG_ENTER_FUNCTION(); |
|
809 |
|
810 if (mCameraDeviceControl.mode() == Cxe::VideoMode) { |
|
811 // Need to store snapshot for ui to be able to get it also later. |
|
812 mSnapshot = snapshot; |
|
813 emit snapshotReady(status, snapshot, filename()); |
|
814 } |
|
815 |
|
816 CX_DEBUG_EXIT_FUNCTION(); |
|
817 } |
1227 |
818 |
1228 /*! |
819 /*! |
1229 * setting has changed, check if we are interested. |
820 * setting has changed, check if we are interested. |
1230 */ |
821 */ |
1231 void CxeVideoCaptureControlSymbian::handleSettingValueChanged(const QString& settingId, |
822 void CxeVideoCaptureControlSymbian::handleSettingValueChanged(const QString& settingId, |