|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include <QTime> |
|
18 #include <fbs.h> |
|
19 #include <QPixmap> |
|
20 #include <coemain.h> |
|
21 #include <QStringList> |
|
22 #include <AudioPreference.h> |
|
23 |
|
24 #include "cxevideocapturecontrolsymbian.h" |
|
25 #include "cxevideorecorderutilitysymbian.h" |
|
26 #include "cxecameradevicecontrolsymbian.h" |
|
27 #include "cxefilenamegeneratorsymbian.h" |
|
28 #include "cxeerrormappingsymbian.h" |
|
29 #include "cxeviewfindercontrol.h" |
|
30 #include "cxestillimagesymbian.h" |
|
31 #include "cxecameradevice.h" |
|
32 #include "cxutils.h" |
|
33 #include "cxesysutil.h" |
|
34 #include "cxestate.h" |
|
35 #include "cxesettings.h" |
|
36 #include "cxenamespace.h" |
|
37 #include "OstTraceDefinitions.h" |
|
38 #include "cxesoundplayersymbian.h" |
|
39 #include "cxequalitypresetssymbian.h" |
|
40 #include "cxeviewfindercontrolsymbian.h" |
|
41 #ifdef OST_TRACE_COMPILER_IN_USE |
|
42 #include "cxevideocapturecontrolsymbianTraces.h" |
|
43 #endif |
|
44 |
|
45 |
|
46 // constants |
|
47 const TInt64 KMinRequiredSpaceVideo = 4000000; |
|
48 const uint KOneMillion = 1000000; |
|
49 const qreal KMetaDataCoeff = 1.03; // Coefficient to estimate metadata amount |
|
50 const uint KCamCMaxClipDurationInSecs = 5400; // Maximun video clip duration in seconds |
|
51 const qreal KCMRAvgVideoBitRateScaler = 0.9; // avg video bit rate scaler |
|
52 |
|
53 |
|
54 /*! |
|
55 * CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian |
|
56 */ |
|
57 CxeVideoCaptureControlSymbian::CxeVideoCaptureControlSymbian(CxeCameraDevice &cameraDevice, |
|
58 CxeViewfinderControl &viewfinderControl, |
|
59 CxeCameraDeviceControl &cameraDeviceControl, |
|
60 CxeFilenameGenerator &nameGenerator, |
|
61 CxeSettings &settings, |
|
62 CxeQualityPresets &qualityPresets) : |
|
63 CxeStateMachine("CxeVideoCaptureControlSymbian"), |
|
64 mVideoRecorder(NULL), |
|
65 mCameraDevice(cameraDevice), |
|
66 mCameraDeviceControl(cameraDeviceControl), |
|
67 mViewfinderControl(viewfinderControl), |
|
68 mFilenameGenerator(nameGenerator), |
|
69 mSettings(settings), |
|
70 mQualityPresets(qualityPresets), |
|
71 mSnapshot(), |
|
72 mNewFileName(""), |
|
73 mCurrentFilename("") |
|
74 { |
|
75 CX_DEBUG_ENTER_FUNCTION(); |
|
76 |
|
77 qRegisterMetaType<CxeVideoCaptureControl::State> (); |
|
78 initializeStates(); |
|
79 mVideoStopSoundPlayer = new |
|
80 CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStop); |
|
81 mVideoStartSoundPlayer = new |
|
82 CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStart); |
|
83 |
|
84 // connect signals from cameraDevice, so we recieve events when camera reference changes |
|
85 connect(&cameraDevice, SIGNAL(prepareForCameraDelete()), |
|
86 this, SLOT(prepareForCameraDelete())); |
|
87 connect(&cameraDevice, SIGNAL(prepareForRelease()), |
|
88 this, SLOT(prepareForRelease()) ); |
|
89 connect(&cameraDevice, SIGNAL(cameraAllocated(CxeError::Id)), |
|
90 this, SLOT(handleCameraAllocated(CxeError::Id))); |
|
91 // connect playing sound signals |
|
92 connect(mVideoStartSoundPlayer, SIGNAL(playComplete(int)), |
|
93 this, SLOT(handleSoundPlayed())); |
|
94 |
|
95 // enabling setting change callbacks to videocapturecontrol |
|
96 connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)), |
|
97 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
|
98 |
|
99 CX_DEBUG_EXIT_FUNCTION(); |
|
100 } |
|
101 |
|
102 |
|
103 /*! |
|
104 * CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
|
105 */ |
|
106 CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
|
107 { |
|
108 CX_DEBUG_ENTER_FUNCTION(); |
|
109 |
|
110 releaseResources(); |
|
111 mIcmSupportedVideoResolutions.clear(); |
|
112 delete mVideoStartSoundPlayer; |
|
113 delete mVideoStopSoundPlayer; |
|
114 |
|
115 CX_DEBUG_EXIT_FUNCTION(); |
|
116 } |
|
117 |
|
118 |
|
119 /*! |
|
120 * Initializes resources for video recording. |
|
121 */ |
|
122 void CxeVideoCaptureControlSymbian::init() |
|
123 { |
|
124 CX_DEBUG_ENTER_FUNCTION(); |
|
125 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 1" ); |
|
126 |
|
127 if (state() == Idle) { |
|
128 // start initializing resources for video capture |
|
129 initVideoRecorder(); |
|
130 } else if (state() == Initialized) { |
|
131 // video recorder already initalized. Continue to prepare video reocording. |
|
132 open(); |
|
133 } |
|
134 |
|
135 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 0" ); |
|
136 |
|
137 CX_DEBUG_EXIT_FUNCTION(); |
|
138 } |
|
139 |
|
140 |
|
141 /* |
|
142 * Releases all resources |
|
143 */ |
|
144 void CxeVideoCaptureControlSymbian::deinit() |
|
145 { |
|
146 CX_DEBUG_ENTER_FUNCTION(); |
|
147 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" ); |
|
148 |
|
149 if(state() == Idle) { |
|
150 // nothing to do |
|
151 return; |
|
152 } |
|
153 |
|
154 // first stop viewfinder |
|
155 mViewfinderControl.stop(); |
|
156 |
|
157 // stop video-recording in-case if its ongoing. |
|
158 stop(); |
|
159 |
|
160 if (mCameraDevice.cameraSnapshot()) { |
|
161 mCameraDevice.cameraSnapshot()->StopSnapshot(); |
|
162 } |
|
163 |
|
164 if (mVideoRecorder) { |
|
165 mVideoRecorder->Close(); |
|
166 } |
|
167 |
|
168 // revert back the new filename to empty string so that we generate a new file name |
|
169 // when we init again |
|
170 mNewFileName = QString(""); |
|
171 |
|
172 setState(Idle); |
|
173 |
|
174 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" ); |
|
175 |
|
176 CX_DEBUG_EXIT_FUNCTION(); |
|
177 } |
|
178 |
|
179 |
|
180 /*! |
|
181 * Intializes VideoRecorder for recording. |
|
182 */ |
|
183 void CxeVideoCaptureControlSymbian::initVideoRecorder() |
|
184 { |
|
185 CX_DEBUG_ENTER_FUNCTION(); |
|
186 |
|
187 if (state() != Idle) { |
|
188 // not valid state to start "open" operation |
|
189 return; |
|
190 } |
|
191 |
|
192 if(!mVideoRecorder) { |
|
193 // if video recorder is not created, do it now. |
|
194 createVideoRecorder(); |
|
195 } |
|
196 |
|
197 // update current video quality details from icm |
|
198 CxeError::Id err = getVideoQualityDetails(mCurrentVideoDetails); |
|
199 |
|
200 if (!err) { |
|
201 // read videofile mime type |
|
202 QByteArray videoFileData = |
|
203 mCurrentVideoDetails.mVideoFileMimeType.toLatin1(); |
|
204 TPtrC8 videoFileMimeType(reinterpret_cast<const TUint8*> |
|
205 (videoFileData.constData()), videoFileData.size()); |
|
206 |
|
207 // read preferred supplier |
|
208 TPtrC16 supplier(reinterpret_cast<const TUint16*> |
|
209 (mCurrentVideoDetails.mPreferredSupplier.utf16())); |
|
210 |
|
211 err = findVideoController(videoFileMimeType, supplier); |
|
212 |
|
213 if (!err) { |
|
214 // video recorder is ready to open video file for recording. |
|
215 setState(Initialized); |
|
216 open(); |
|
217 } |
|
218 } else { |
|
219 err = CxeErrorHandlingSymbian::map(KErrNotReady); |
|
220 } |
|
221 |
|
222 if (err) { |
|
223 // In case of error |
|
224 emit videoPrepareComplete(err); |
|
225 deinit(); |
|
226 } |
|
227 |
|
228 CX_DEBUG_EXIT_FUNCTION(); |
|
229 } |
|
230 |
|
231 |
|
232 |
|
233 /*! |
|
234 * Opens file for video recording. |
|
235 */ |
|
236 void CxeVideoCaptureControlSymbian::open() |
|
237 { |
|
238 CX_DEBUG_ENTER_FUNCTION(); |
|
239 |
|
240 if (state() != Initialized) { |
|
241 // not valid state to start "open" operation |
|
242 return; |
|
243 } |
|
244 |
|
245 CxeError::Id err = CxeError::None; |
|
246 |
|
247 // generate video file name, if necessary |
|
248 if (mNewFileName.isEmpty()) { |
|
249 QStringList list = mCurrentVideoDetails.mVideoFileMimeType.split("/"); |
|
250 QString fileExt("."); |
|
251 if (list.count() == 2) { |
|
252 fileExt = fileExt + list[1]; |
|
253 } |
|
254 // Generate new filename and open the file for writing video data |
|
255 err = mFilenameGenerator.generateFilename(mNewFileName, fileExt); |
|
256 if (err == CxeError::None) { |
|
257 mCurrentFilename = mNewFileName; |
|
258 } else { |
|
259 // file name is not valid, re-initialize the value of current string |
|
260 // back to empty string |
|
261 mCurrentFilename = QString(""); |
|
262 } |
|
263 } |
|
264 |
|
265 if (!err && |
|
266 mVideoRecorder && |
|
267 !mCurrentFilename.isEmpty()) { |
|
268 |
|
269 TPtrC16 fName(reinterpret_cast<const TUint16*>(mCurrentFilename.utf16())); |
|
270 CX_DEBUG(( "Next video file path: %s", mCurrentFilename.toAscii().constData() )); |
|
271 |
|
272 // read video codec mime type |
|
273 QByteArray videoCodecData = |
|
274 mCurrentVideoDetails.mVideoCodecMimeType.toLatin1(); |
|
275 TPtrC8 videoCodecMimeType(reinterpret_cast<const TUint8*> |
|
276 (videoCodecData.constData()), videoCodecData.size()); |
|
277 |
|
278 setState(CxeVideoCaptureControl::Preparing); |
|
279 |
|
280 TRAPD(openErr, mVideoRecorder->OpenFileL(fName, |
|
281 mCameraDevice.camera()->Handle(), |
|
282 mVideoControllerUid, |
|
283 mVideoFormatUid, |
|
284 videoCodecMimeType, |
|
285 audioType(mCurrentVideoDetails.mAudioType))); |
|
286 |
|
287 err = CxeErrorHandlingSymbian::map(openErr); |
|
288 } |
|
289 if (err) { |
|
290 // error occured. |
|
291 deinit(); |
|
292 emit videoPrepareComplete(err); |
|
293 } |
|
294 CX_DEBUG_EXIT_FUNCTION(); |
|
295 } |
|
296 |
|
297 |
|
298 /*! |
|
299 * Prepare Video Recorder with necessary settings for video capture. |
|
300 */ |
|
301 TFourCC CxeVideoCaptureControlSymbian::audioType(const QString& str) |
|
302 { |
|
303 CX_DEBUG_ENTER_FUNCTION(); |
|
304 |
|
305 QByteArray audioType = str.toAscii(); |
|
306 |
|
307 quint8 char1(' '); |
|
308 quint8 char2(' '); |
|
309 quint8 char3(' '); |
|
310 quint8 char4(' '); |
|
311 |
|
312 if (audioType.count() > 3) { |
|
313 char1 = audioType[0]; |
|
314 char2 = audioType[1]; |
|
315 char3 = audioType[2]; |
|
316 |
|
317 if (audioType.count() == 4) { |
|
318 char4 = audioType[3]; |
|
319 } |
|
320 } |
|
321 |
|
322 return TFourCC(char1, char2, char3, char4); |
|
323 } |
|
324 |
|
325 |
|
326 /*! |
|
327 * Prepare Video Recorder with necessary settings for video capture. |
|
328 */ |
|
329 void CxeVideoCaptureControlSymbian::prepare() |
|
330 { |
|
331 CX_DEBUG_ENTER_FUNCTION(); |
|
332 |
|
333 if (state() != Preparing) { |
|
334 // not valid state to continue prepare. |
|
335 return; |
|
336 } |
|
337 |
|
338 CX_DEBUG(("Video resoulution (%d,%d)", mCurrentVideoDetails.mWidth, |
|
339 mCurrentVideoDetails.mHeight)); |
|
340 CX_DEBUG(("Video bitrate = %d)", mCurrentVideoDetails.mVideoBitRate)); |
|
341 CX_DEBUG(("Video frame rate = %f)", mCurrentVideoDetails.mVideoFrameRate)); |
|
342 |
|
343 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_VIDCAPCONT_PREPARE 1"); |
|
344 TSize frameSize; |
|
345 frameSize.SetSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight); |
|
346 |
|
347 int muteSetting = 0; // audio enabled |
|
348 mSettings.get(CxeSettingIds::VIDEO_MUTE_SETTING, muteSetting); |
|
349 |
|
350 TRAPD(err, |
|
351 { |
|
352 mVideoRecorder->SetVideoFrameSizeL(frameSize); |
|
353 mVideoRecorder->SetVideoFrameRateL(mCurrentVideoDetails.mVideoFrameRate); |
|
354 mVideoRecorder->SetVideoBitRateL(mCurrentVideoDetails.mVideoBitRate); |
|
355 mVideoRecorder->SetAudioEnabledL(muteSetting == 0); |
|
356 // "No limit" value is handled in video recorder wrapper. |
|
357 mVideoRecorder->SetMaxClipSizeL(mCurrentVideoDetails.mMaximumSizeInBytes); |
|
358 } |
|
359 ); |
|
360 |
|
361 if (!err) { |
|
362 // settings have been applied successfully, start to prepare |
|
363 mVideoRecorder->Prepare(); |
|
364 // prepare snapshot |
|
365 err = prepareVideoSnapshot(); |
|
366 } |
|
367 |
|
368 if (!err) { |
|
369 // prepare zoom only when there are no errors during prepare. |
|
370 emit prepareZoomForVideo(); |
|
371 } |
|
372 // emit video prepare status |
|
373 emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err)); |
|
374 |
|
375 OstTrace0(camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_VIDCAPCONT_PREPARE 0"); |
|
376 |
|
377 CX_DEBUG_EXIT_FUNCTION(); |
|
378 } |
|
379 |
|
380 |
|
381 |
|
382 /*! |
|
383 Fetches video qualites details based on video quality setting. |
|
384 Returns CxeError codes if any. |
|
385 */ |
|
386 CxeError::Id |
|
387 CxeVideoCaptureControlSymbian::getVideoQualityDetails(CxeVideoDetails &videoInfo) |
|
388 { |
|
389 CX_DEBUG_ENTER_FUNCTION(); |
|
390 |
|
391 int videoQuality = 0; |
|
392 CxeError::Id err = CxeError::None; |
|
393 |
|
394 if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { |
|
395 err = mSettings.get(CxeSettingIds::VIDEO_QUALITY, videoQuality); |
|
396 |
|
397 bool validQuality = (videoQuality >= 0 && |
|
398 videoQuality < mIcmSupportedVideoResolutions.count()); |
|
399 if (err == CxeError::None && validQuality) { |
|
400 // get video quality details |
|
401 videoInfo = mIcmSupportedVideoResolutions.at(videoQuality); |
|
402 } else { |
|
403 // not valid video quality |
|
404 err = CxeError::NotFound; |
|
405 } |
|
406 } else { |
|
407 // get secondary camera video quality index |
|
408 if (mIcmSupportedVideoResolutions.count() > 0) { |
|
409 videoInfo = mIcmSupportedVideoResolutions.at(videoQuality); |
|
410 } else { |
|
411 // not valid video quality |
|
412 err = CxeError::NotFound; |
|
413 } |
|
414 } |
|
415 |
|
416 CX_DEBUG_EXIT_FUNCTION(); |
|
417 |
|
418 return err; |
|
419 } |
|
420 |
|
421 |
|
422 /**! |
|
423 Prepare snapshot |
|
424 Returns symbian error code. |
|
425 */ |
|
426 int CxeVideoCaptureControlSymbian::prepareVideoSnapshot() |
|
427 { |
|
428 CX_DEBUG_ENTER_FUNCTION(); |
|
429 |
|
430 CCamera::CCameraSnapshot *cameraSnapshot = mCameraDevice.cameraSnapshot(); |
|
431 CX_ASSERT_ALWAYS(cameraSnapshot); |
|
432 |
|
433 int err = KErrNone; |
|
434 // Whether or not we have postcapture on, we need the snapshot for Thumbnail Manager. |
|
435 if (cameraSnapshot) { |
|
436 // Cancel active snapshot |
|
437 cameraSnapshot->StopSnapshot(); |
|
438 |
|
439 // Prepare snapshot |
|
440 CCamera::TFormat snapFormat = CCamera::EFormatFbsBitmapColor16MU; |
|
441 TRAP(err, cameraSnapshot->PrepareSnapshotL(snapFormat, |
|
442 getSnapshotSize(), |
|
443 KMaintainAspectRatio)); |
|
444 CX_DEBUG(("PrepareSnapshotL done, err=%d", err)); |
|
445 // Start snapshot if no errors encountered. |
|
446 if (err == KErrNone) { |
|
447 CX_DEBUG(("Start video snapshot")); |
|
448 cameraSnapshot->StartSnapshot(); |
|
449 } |
|
450 } else { |
|
451 // No snapshot interface available. Report error. |
|
452 // Assert above takes care of this, but keeping this as an option. |
|
453 err = KErrNotReady; |
|
454 } |
|
455 |
|
456 CX_DEBUG_EXIT_FUNCTION(); |
|
457 |
|
458 return err; |
|
459 } |
|
460 |
|
461 |
|
462 |
|
463 /*! |
|
464 * Returns snapshot size. Snapshot size is calculated based on the |
|
465 * display resolution and current video aspect ratio. |
|
466 */ |
|
467 TSize CxeVideoCaptureControlSymbian::getSnapshotSize() const |
|
468 { |
|
469 CX_DEBUG_ENTER_FUNCTION(); |
|
470 |
|
471 TSize snapshotSize; |
|
472 |
|
473 QSize deviceResolution = mViewfinderControl.deviceDisplayResolution(); |
|
474 QSize size = QSize(mCurrentVideoDetails.mWidth, mCurrentVideoDetails.mHeight); |
|
475 |
|
476 // scale according to aspect ratio. |
|
477 size.scale(deviceResolution.width(), |
|
478 deviceResolution.height(), |
|
479 Qt::KeepAspectRatio); |
|
480 CX_DEBUG(("Video Snapshot size, (%d,%d)", size.width(), size.height())); |
|
481 snapshotSize.SetSize(size.width(), deviceResolution.height()); |
|
482 |
|
483 CX_DEBUG_EXIT_FUNCTION(); |
|
484 |
|
485 return snapshotSize; |
|
486 } |
|
487 |
|
488 |
|
489 |
|
490 /**! |
|
491 * Camera events coming from ecam. |
|
492 */ |
|
493 void CxeVideoCaptureControlSymbian::handleCameraEvent(int eventUid, int error) |
|
494 { |
|
495 CX_DEBUG_ENTER_FUNCTION(); |
|
496 if (eventUid == KUidECamEventSnapshotUidValue) { |
|
497 handleSnapshotEvent(CxeErrorHandlingSymbian::map(error)); |
|
498 } |
|
499 CX_DEBUG_EXIT_FUNCTION(); |
|
500 } |
|
501 |
|
502 |
|
503 /*! |
|
504 * Handle Snapshot event from ecam |
|
505 */ |
|
506 void CxeVideoCaptureControlSymbian::handleSnapshotEvent(CxeError::Id error) |
|
507 { |
|
508 CX_DEBUG_ENTER_FUNCTION(); |
|
509 |
|
510 if (state() == Idle) { |
|
511 // we ignore this event, when we are not in active state(s) |
|
512 CX_DEBUG(( "wrong state, ignoring snapshot" )); |
|
513 CX_DEBUG_EXIT_FUNCTION(); |
|
514 return; |
|
515 } |
|
516 |
|
517 if (error) { |
|
518 mSnapshot = QPixmap(); |
|
519 emit snapshotReady(error, mSnapshot, filename()); |
|
520 return; |
|
521 } |
|
522 |
|
523 RArray<TInt> snapList; |
|
524 MCameraBuffer* buffer(NULL); |
|
525 // Note: Cleanup not required in this function |
|
526 CFbsBitmap *snapshot = NULL; |
|
527 TRAPD(snapErr, |
|
528 buffer = &mCameraDevice.cameraSnapshot()->SnapshotDataL(snapList)); |
|
529 if (!snapErr) { |
|
530 TInt firstImageIndex = snapList.Find(0); |
|
531 snapList.Close(); |
|
532 TRAP(snapErr, snapshot = &(buffer->BitmapL(firstImageIndex))); |
|
533 } |
|
534 if (!snapErr) { |
|
535 TSize size = snapshot->SizeInPixels(); |
|
536 TInt sizeInWords = size.iHeight * CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU) |
|
537 / sizeof(TUint32); |
|
538 |
|
539 TUint32 *snapshotData = NULL; |
|
540 snapshotData = new TUint32[sizeInWords]; |
|
541 |
|
542 if (snapshotData) { |
|
543 // Convert to QImage |
|
544 snapshot->LockHeap(); |
|
545 TUint32* dataPtr = snapshot->DataAddress(); |
|
546 memcpy(snapshotData, dataPtr, sizeof(TUint32) * sizeInWords); |
|
547 snapshot->UnlockHeap(); |
|
548 |
|
549 |
|
550 QImage *img = new QImage((uchar*) snapshotData, size.iWidth, size.iHeight, |
|
551 CFbsBitmap::ScanLineLength(size.iWidth, EColor16MU), |
|
552 QImage::Format_RGB32); |
|
553 |
|
554 mSnapshot = QPixmap::fromImage(*img); |
|
555 delete [] snapshotData; |
|
556 delete img; |
|
557 } |
|
558 } |
|
559 if (buffer) { |
|
560 buffer->Release(); |
|
561 } |
|
562 // Snapshot ready |
|
563 emit snapshotReady(CxeErrorHandlingSymbian::map(snapErr), mSnapshot, filename()); |
|
564 |
|
565 CX_DEBUG_EXIT_FUNCTION(); |
|
566 } |
|
567 |
|
568 |
|
569 /*! |
|
570 * Resets the video snapshot and current video filename |
|
571 */ |
|
572 void CxeVideoCaptureControlSymbian::reset() |
|
573 { |
|
574 CX_DEBUG_ENTER_FUNCTION(); |
|
575 |
|
576 // Snapshot will consume considerably memory. |
|
577 // Replace it with null pixmap to have it freed. |
|
578 mSnapshot = QPixmap(); |
|
579 // reset the current file name. |
|
580 mCurrentFilename = QString(""); |
|
581 |
|
582 CX_DEBUG_EXIT_FUNCTION(); |
|
583 } |
|
584 |
|
585 |
|
586 /*! |
|
587 * Returns current video filename |
|
588 */ |
|
589 QString CxeVideoCaptureControlSymbian::filename() const |
|
590 { |
|
591 // Simply return the current contents of mCurrentFilename. |
|
592 // If video recording was started then it returns proper filename |
|
593 // otherwise an empty string is returned. |
|
594 return mCurrentFilename; |
|
595 } |
|
596 |
|
597 |
|
598 /*! |
|
599 * Returns current video snapshot |
|
600 */ |
|
601 QPixmap CxeVideoCaptureControlSymbian::snapshot() const |
|
602 { |
|
603 return mSnapshot; |
|
604 } |
|
605 |
|
606 |
|
607 /*! |
|
608 * Starts video recording if we are in appropriate state. |
|
609 */ |
|
610 void CxeVideoCaptureControlSymbian::record() |
|
611 { |
|
612 CX_DEBUG_ENTER_FUNCTION(); |
|
613 |
|
614 if (state() == Ready || state() == Paused) { |
|
615 // ask the player to play the sound |
|
616 // recording will start once start sound is played |
|
617 setState(CxeVideoCaptureControl::PlayingStartSound); |
|
618 mVideoStartSoundPlayer->play(); |
|
619 } |
|
620 |
|
621 CX_DEBUG_EXIT_FUNCTION(); |
|
622 } |
|
623 |
|
624 |
|
625 /*! |
|
626 * Pauses video recording. |
|
627 */ |
|
628 void CxeVideoCaptureControlSymbian::pause() |
|
629 { |
|
630 CX_DEBUG_ENTER_FUNCTION(); |
|
631 |
|
632 setState(CxeVideoCaptureControl::Paused); |
|
633 TRAPD(pauseErr, mVideoRecorder->PauseL()); |
|
634 if (pauseErr) { |
|
635 CX_DEBUG(("[WARNING] Error %d pausing!", pauseErr)); |
|
636 //pause operation failed, report it |
|
637 emit videoComposed(CxeErrorHandlingSymbian::map(pauseErr), filename()); |
|
638 // release resources. |
|
639 deinit(); |
|
640 } |
|
641 |
|
642 CX_DEBUG_EXIT_FUNCTION(); |
|
643 } |
|
644 |
|
645 |
|
646 /*! |
|
647 * Stops video recording. |
|
648 */ |
|
649 void CxeVideoCaptureControlSymbian::stop() |
|
650 { |
|
651 CX_DEBUG_ENTER_FUNCTION(); |
|
652 |
|
653 if (state() == Recording || state() == Paused) { |
|
654 // first stop viewfinder |
|
655 mViewfinderControl.stop(); |
|
656 |
|
657 TInt asyncStopErr = mVideoRecorder->CustomCommandSync( |
|
658 TMMFMessageDestination(KCamCControllerImplementationUid, |
|
659 KMMFObjectHandleController), |
|
660 ECamCControllerCCVideoStopAsync, |
|
661 KNullDesC8, |
|
662 KNullDesC8 ); |
|
663 CX_DEBUG(("ECamCControllerCCVideoStopAsync sent, err=%d", asyncStopErr)); |
|
664 if (asyncStopErr) { // fall back to synchronous stop |
|
665 TInt syncStopErr = mVideoRecorder->Stop(); |
|
666 if (syncStopErr) { |
|
667 // error during stop operation, release resources |
|
668 emit videoComposed(CxeErrorHandlingSymbian::map(asyncStopErr), filename()); |
|
669 deinit(); |
|
670 } else { |
|
671 // stop operation went fine, set back the state to Initialized. |
|
672 setState(Initialized); |
|
673 mFilenameGenerator.raiseCounterValue(); |
|
674 } |
|
675 } else { |
|
676 // No error from asynch stop custom command... wait for stop event |
|
677 setState(Stopping); |
|
678 mFilenameGenerator.raiseCounterValue(); |
|
679 } |
|
680 } |
|
681 |
|
682 CX_DEBUG_EXIT_FUNCTION(); |
|
683 } |
|
684 |
|
685 |
|
686 /*! |
|
687 * Callback when "Open" operation is complete. |
|
688 */ |
|
689 void CxeVideoCaptureControlSymbian::MvruoOpenComplete(TInt aError) |
|
690 { |
|
691 CX_DEBUG_ENTER_FUNCTION(); |
|
692 CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoOpenComplete, err=%d", aError)); |
|
693 |
|
694 if (state() == Preparing) { |
|
695 if (aError != KErrNone) { |
|
696 deinit(); |
|
697 CxeError::Id err = CxeErrorHandlingSymbian::map(KErrNotReady); |
|
698 // report error to interested parties |
|
699 emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err)); |
|
700 } else { |
|
701 prepare(); |
|
702 } |
|
703 } |
|
704 |
|
705 CX_DEBUG_EXIT_FUNCTION(); |
|
706 } |
|
707 |
|
708 |
|
709 /*! |
|
710 * Callback when "Prepare" request is complete. |
|
711 */ |
|
712 void CxeVideoCaptureControlSymbian::MvruoPrepareComplete(TInt aError) |
|
713 { |
|
714 CX_DEBUG_ENTER_FUNCTION(); |
|
715 CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoPrepareComplete, err=%d", aError)); |
|
716 |
|
717 if (state() == Preparing) { |
|
718 if (!aError) { |
|
719 setState(CxeVideoCaptureControl::Ready); |
|
720 mViewfinderControl.start(); |
|
721 } else { |
|
722 deinit(); |
|
723 // report error to interested parties |
|
724 CxeError::Id err = CxeErrorHandlingSymbian::map(KErrNotReady); |
|
725 emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err)); |
|
726 } |
|
727 } |
|
728 |
|
729 CX_DEBUG_EXIT_FUNCTION(); |
|
730 } |
|
731 |
|
732 |
|
733 /*! |
|
734 * Callback when "Record" operation is complete. |
|
735 */ |
|
736 void CxeVideoCaptureControlSymbian::MvruoRecordComplete(TInt aError) |
|
737 { |
|
738 CX_DEBUG_ENTER_FUNCTION(); |
|
739 CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoRecordComplete, err=%d", aError)); |
|
740 |
|
741 //! async stop customcommand stuff |
|
742 if (aError == KErrNone) { |
|
743 setState(CxeVideoCaptureControl::Ready); |
|
744 } else if (aError == KErrCompletion) { |
|
745 // KErrCompletion is received when video recording stops |
|
746 // because of maximum clip size is reached. Emulate |
|
747 // normal stopping. |
|
748 setState(Stopping); |
|
749 MvruoEvent(TMMFEvent(KCamCControllerCCVideoRecordStopped, KErrNone)); |
|
750 MvruoEvent(TMMFEvent(KCamCControllerCCVideoFileComposed, KErrNone)); |
|
751 } |
|
752 else { |
|
753 // error during recording, report to client |
|
754 deinit(); |
|
755 emit videoComposed(CxeErrorHandlingSymbian::map(aError), filename()); |
|
756 } |
|
757 |
|
758 CX_DEBUG_EXIT_FUNCTION(); |
|
759 } |
|
760 |
|
761 |
|
762 /*! |
|
763 * Callback from MVideoRecorderUtilityObserver |
|
764 */ |
|
765 void CxeVideoCaptureControlSymbian::MvruoEvent(const TMMFEvent& aEvent) |
|
766 { |
|
767 CX_DEBUG_ENTER_FUNCTION(); |
|
768 |
|
769 if (aEvent.iEventType.iUid == KCamCControllerCCVideoRecordStopped.iUid) { |
|
770 CX_DEBUG(("KCamCControllerCCVideoRecordStopped")); |
|
771 // play the sound, but not changing the state |
|
772 mVideoStopSoundPlayer->play(); |
|
773 } else if (aEvent.iEventType.iUid == KCamCControllerCCVideoFileComposed.iUid) { |
|
774 CX_DEBUG(("KCamCControllerCCVideoFileComposed")); |
|
775 if (state() == Stopping) { |
|
776 // stop operation went fine, set back the state to intialized. |
|
777 setState(Initialized); |
|
778 } |
|
779 // video file has composed, everything went well, inform the client |
|
780 emit videoComposed(CxeError::None, filename()); |
|
781 // revert back the new filename to empty string, since recording |
|
782 // is complete and we need to generate a new file name |
|
783 mNewFileName = QString(""); |
|
784 } else { |
|
785 CX_DEBUG(("ignoring unknown MvruoEvent 0x%08x", aEvent.iEventType.iUid )); |
|
786 } |
|
787 |
|
788 CX_DEBUG_EXIT_FUNCTION(); |
|
789 } |
|
790 |
|
791 |
|
792 /*! |
|
793 Get corresponding controller for video capture. |
|
794 @param aMimeType denotes videofile mimetype, |
|
795 @param aPreferredSupplier denotes supplier. |
|
796 Returns CxeError::Id if any. |
|
797 */ |
|
798 CxeError::Id |
|
799 CxeVideoCaptureControlSymbian::findVideoController(const TDesC8& aMimeType, |
|
800 const TDesC& aSupplier) |
|
801 { |
|
802 CX_DEBUG_ENTER_FUNCTION(); |
|
803 |
|
804 CX_DEBUG(("video file mime type : %s", &aMimeType)); |
|
805 CX_DEBUG(("supplier name: %s", &aSupplier)); |
|
806 |
|
807 mVideoControllerUid.iUid = 0; |
|
808 mVideoFormatUid.iUid = 0; |
|
809 |
|
810 // Retrieve a list of possible controllers from ECOM. |
|
811 // Controller must support recording the requested mime type. |
|
812 // Controller must be provided by preferred supplier. |
|
813 |
|
814 CMMFControllerPluginSelectionParameters* cSelect(NULL); |
|
815 CMMFFormatSelectionParameters* fSelect(NULL); |
|
816 RMMFControllerImplInfoArray controllers; |
|
817 |
|
818 TRAPD(err, cSelect = CMMFControllerPluginSelectionParameters::NewL()); |
|
819 if (err) { |
|
820 return CxeErrorHandlingSymbian::map(err); |
|
821 } |
|
822 |
|
823 TRAP(err, fSelect = CMMFFormatSelectionParameters::NewL()); |
|
824 if (err) { |
|
825 if(cSelect) { |
|
826 delete cSelect; |
|
827 } |
|
828 return CxeErrorHandlingSymbian::map(err); |
|
829 } |
|
830 |
|
831 TRAP( err, { |
|
832 fSelect->SetMatchToMimeTypeL(aMimeType); |
|
833 cSelect->SetRequiredRecordFormatSupportL(*fSelect); |
|
834 cSelect->SetPreferredSupplierL(aSupplier, |
|
835 CMMFPluginSelectionParameters::EOnlyPreferredSupplierPluginsReturned); |
|
836 cSelect->ListImplementationsL(controllers); |
|
837 } ); |
|
838 |
|
839 if (!err && controllers.Count() >= 1) { |
|
840 // KErrNotFound is returned unless a controller is found |
|
841 err = KErrNotFound; |
|
842 // Get the controller UID. |
|
843 mVideoControllerUid = controllers[0]->Uid(); |
|
844 |
|
845 // Inquires the controller about supported formats. |
|
846 // We use the first controller found having index 0. |
|
847 RMMFFormatImplInfoArray formats; |
|
848 formats = controllers[0]->RecordFormats(); |
|
849 |
|
850 // Get the first format that supports our mime type. |
|
851 int count = formats.Count(); |
|
852 for (int i=0; i<count; i++) { |
|
853 if (formats[i]->SupportsMimeType(aMimeType)) { |
|
854 mVideoFormatUid = formats[i]->Uid(); // set the UID |
|
855 err = KErrNone; |
|
856 break; |
|
857 } |
|
858 } |
|
859 } |
|
860 delete cSelect; |
|
861 delete fSelect; |
|
862 controllers.ResetAndDestroy(); |
|
863 |
|
864 CX_DEBUG_EXIT_FUNCTION(); |
|
865 |
|
866 return CxeErrorHandlingSymbian::map(err); |
|
867 } |
|
868 |
|
869 |
|
870 /*! |
|
871 * camera reference changing, release resources |
|
872 */ |
|
873 void CxeVideoCaptureControlSymbian::prepareForCameraDelete() |
|
874 { |
|
875 CX_DEBUG_ENTER_FUNCTION(); |
|
876 releaseResources(); |
|
877 CX_DEBUG_EXIT_FUNCTION(); |
|
878 } |
|
879 |
|
880 /*! |
|
881 * prepare for camera release. |
|
882 */ |
|
883 void CxeVideoCaptureControlSymbian::prepareForRelease() |
|
884 { |
|
885 CX_DEBUG_ENTER_FUNCTION(); |
|
886 deinit(); |
|
887 CX_DEBUG_EXIT_FUNCTION(); |
|
888 } |
|
889 |
|
890 |
|
891 /*! |
|
892 * new camera available, |
|
893 */ |
|
894 void CxeVideoCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) |
|
895 { |
|
896 CX_DEBUG_ENTER_FUNCTION(); |
|
897 |
|
898 if (!error) { |
|
899 // initialize the video recorder utility |
|
900 createVideoRecorder(); |
|
901 // new camera available, read supported video qualities from icm |
|
902 // load all still qualities supported by icm |
|
903 mIcmSupportedVideoResolutions.clear(); |
|
904 Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex(); |
|
905 // get list of supported image qualities based on camera index |
|
906 mIcmSupportedVideoResolutions = |
|
907 mQualityPresets.videoQualityPresets(cameraIndex); |
|
908 } |
|
909 |
|
910 CX_DEBUG_EXIT_FUNCTION(); |
|
911 } |
|
912 |
|
913 |
|
914 /*! |
|
915 * Initializes video recorder. |
|
916 */ |
|
917 void CxeVideoCaptureControlSymbian::createVideoRecorder() |
|
918 { |
|
919 CX_DEBUG_ENTER_FUNCTION(); |
|
920 |
|
921 // init video recoder |
|
922 if (state() == CxeVideoCaptureControl::Idle) { |
|
923 if (mVideoRecorder == NULL) { |
|
924 TRAPD(initErr, mVideoRecorder = |
|
925 new CxeVideoRecorderUtilitySymbian( *this , |
|
926 KAudioPriorityVideoRecording, |
|
927 TMdaPriorityPreference( KAudioPrefVideoRecording ))); |
|
928 if (initErr) { |
|
929 CX_DEBUG(("WARNING - VideoRecorderUtility could not be reserved. Failed with err:%d", initErr)); |
|
930 mVideoRecorder = NULL; |
|
931 } |
|
932 } |
|
933 } |
|
934 |
|
935 CX_DEBUG_EXIT_FUNCTION(); |
|
936 } |
|
937 |
|
938 |
|
939 /*! |
|
940 * releases resources used by videocapture |
|
941 */ |
|
942 void CxeVideoCaptureControlSymbian::releaseResources() |
|
943 { |
|
944 CX_DEBUG_ENTER_FUNCTION(); |
|
945 |
|
946 // Save the state and filename before releasing. |
|
947 QString filenameCopy(filename()); |
|
948 CxeVideoCaptureControl::State stateCopy(state()); |
|
949 |
|
950 // first de-init videocapture control |
|
951 deinit(); |
|
952 reset(); |
|
953 |
|
954 // Check if state is stopping, in which case we have to inform the |
|
955 // file harvester that a file is to be completed. We would not |
|
956 // call harvestFile otherwise in this case. |
|
957 // Otherwise the video will not be found from videos app. |
|
958 if (stateCopy == CxeVideoCaptureControl::Stopping) { |
|
959 emit videoComposed(CxeError::None, filenameCopy); |
|
960 } |
|
961 |
|
962 delete mVideoRecorder; |
|
963 mVideoRecorder = NULL; |
|
964 |
|
965 CX_DEBUG_EXIT_FUNCTION(); |
|
966 } |
|
967 |
|
968 |
|
969 /*! |
|
970 Returns current state of videocapture |
|
971 */ |
|
972 CxeVideoCaptureControl::State CxeVideoCaptureControlSymbian::state() const |
|
973 { |
|
974 return static_cast<CxeVideoCaptureControl::State> (stateId()); |
|
975 } |
|
976 |
|
977 |
|
978 /*! |
|
979 * slot called when state is changed. |
|
980 */ |
|
981 void CxeVideoCaptureControlSymbian::handleStateChanged(int newStateId, CxeError::Id error) |
|
982 { |
|
983 emit stateChanged(static_cast<State> (newStateId), error); |
|
984 } |
|
985 |
|
986 |
|
987 /*! |
|
988 * Initialize states for videocapturecontrol |
|
989 */ |
|
990 void CxeVideoCaptureControlSymbian::initializeStates() |
|
991 { |
|
992 // addState( id, name, allowed next states ) |
|
993 addState(new CxeState(Idle, "Idle", Initialized)); |
|
994 addState(new CxeState(Initialized, "Initialized", Preparing | Idle)); |
|
995 addState(new CxeState(Preparing, "Preparing", Ready | Idle)); |
|
996 addState(new CxeState(Ready, "Ready", Recording | PlayingStartSound | Preparing | Idle)); |
|
997 addState(new CxeState(Recording, "Recording", Recording | Paused | Stopping | Idle)); |
|
998 addState(new CxeState(Paused, "Paused", Recording | Stopping | PlayingStartSound | Idle)); |
|
999 addState(new CxeState(Stopping, "Stopping", Initialized | Idle)); |
|
1000 addState(new CxeState(PlayingStartSound, "PlayingStartSound", Recording | Idle)); |
|
1001 |
|
1002 setInitialState(Idle); |
|
1003 } |
|
1004 |
|
1005 |
|
1006 /*! |
|
1007 * Updates remaining video recordng time counter to all the video qualities supported by ICM |
|
1008 * this should be done whenever storage location setting changes and when values are |
|
1009 * read from ICM for the first time |
|
1010 */ |
|
1011 void CxeVideoCaptureControlSymbian::updateRemainingRecordingTimeCounter() |
|
1012 { |
|
1013 CX_DEBUG_ENTER_FUNCTION(); |
|
1014 |
|
1015 for( int index = 0; index < mIcmSupportedVideoResolutions.count(); index++) { |
|
1016 CxeVideoDetails &qualityDetails = mIcmSupportedVideoResolutions[index]; |
|
1017 calculateRemainingTime(qualityDetails, qualityDetails.mRemainingTime); |
|
1018 } |
|
1019 |
|
1020 CX_DEBUG_EXIT_FUNCTION(); |
|
1021 } |
|
1022 |
|
1023 /* |
|
1024 * calculates remaining video recording time. |
|
1025 */ |
|
1026 void CxeVideoCaptureControlSymbian::remainingTime(int &time) |
|
1027 { |
|
1028 CX_DEBUG_ENTER_FUNCTION(); |
|
1029 |
|
1030 if (state() == CxeVideoCaptureControl::Recording) { |
|
1031 TTimeIntervalMicroSeconds remaining = 0; |
|
1032 remaining = mVideoRecorder->RecordTimeAvailable(); |
|
1033 time = remaining.Int64() * 1.0 / KOneSecond; |
|
1034 CX_DEBUG(( "timeRemaining2: %d", time )); |
|
1035 } else { |
|
1036 calculateRemainingTime(mCurrentVideoDetails, time); |
|
1037 } |
|
1038 |
|
1039 CX_DEBUG_EXIT_FUNCTION(); |
|
1040 } |
|
1041 |
|
1042 |
|
1043 |
|
1044 /*! |
|
1045 * algorithm to calculate remaining recording time |
|
1046 @ param videoDetails contains the current video resolution that is in use. |
|
1047 @ time contains the remaining recording time |
|
1048 */ |
|
1049 void CxeVideoCaptureControlSymbian::calculateRemainingTime(CxeVideoDetails videoDetails, int &time) |
|
1050 { |
|
1051 CX_DEBUG_ENTER_FUNCTION(); |
|
1052 |
|
1053 TTimeIntervalMicroSeconds remaining = 0; |
|
1054 |
|
1055 // get available space in the drive selected in the settings |
|
1056 // for storing videos |
|
1057 qint64 availableSpace = CxeSysUtil::spaceAvailable(CCoeEnv::Static()->FsSession(), mSettings); |
|
1058 |
|
1059 availableSpace = availableSpace - KMinRequiredSpaceVideo; |
|
1060 |
|
1061 // Maximum clip size may be limited for mms quality. |
|
1062 // If mMaximumSizeInBytes == 0, no limit is specified. |
|
1063 if (videoDetails.mMaximumSizeInBytes > 0 && videoDetails.mMaximumSizeInBytes < availableSpace) { |
|
1064 availableSpace = videoDetails.mMaximumSizeInBytes; |
|
1065 } |
|
1066 |
|
1067 // Use average audio/video bitrates to estimate remaining time |
|
1068 quint32 averageBitRate = 0; |
|
1069 quint32 averageByteRate = 0; |
|
1070 qreal scaler = mQualityPresets.avgVideoBitRateScaler(); |
|
1071 |
|
1072 if (scaler == 0) { |
|
1073 // video bit rate scaler is 0, use the constant value |
|
1074 scaler = KCMRAvgVideoBitRateScaler; |
|
1075 } |
|
1076 |
|
1077 int avgVideoBitRate = (videoDetails.mVideoBitRate * scaler); |
|
1078 int avgAudioBitRate = videoDetails.mAudioBitRate; |
|
1079 |
|
1080 int muteSetting = 0; // audio enabled |
|
1081 mSettings.get(CxeSettingIds::VIDEO_MUTE_SETTING, muteSetting); |
|
1082 |
|
1083 if (muteSetting == 1) { |
|
1084 // audio disabled from setting. hence no audio |
|
1085 avgAudioBitRate = 0; |
|
1086 } |
|
1087 |
|
1088 averageBitRate = (quint32)( |
|
1089 (avgVideoBitRate + avgAudioBitRate) * KMetaDataCoeff); |
|
1090 |
|
1091 averageByteRate = averageBitRate / 8; |
|
1092 |
|
1093 if (availableSpace <= 0) { |
|
1094 remaining = 0; |
|
1095 } else { |
|
1096 // converting microseconds to seconds |
|
1097 remaining = availableSpace * KOneMillion / averageByteRate; |
|
1098 if ( (remaining.Int64()) > (quint64(KCamCMaxClipDurationInSecs) * KOneMillion) ) { |
|
1099 remaining = (quint64(KCamCMaxClipDurationInSecs) * KOneMillion); |
|
1100 } |
|
1101 } |
|
1102 if ( remaining <= quint64(0) ) { |
|
1103 remaining = 0; |
|
1104 } |
|
1105 |
|
1106 time = remaining.Int64() * 1.0 / KOneSecond; |
|
1107 |
|
1108 CX_DEBUG(( "remaining time from algorithm: %d", time )); |
|
1109 |
|
1110 CX_DEBUG_EXIT_FUNCTION(); |
|
1111 } |
|
1112 |
|
1113 |
|
1114 /*! |
|
1115 * Calculates remaining recording time during video recording |
|
1116 */ |
|
1117 bool CxeVideoCaptureControlSymbian::elapsedTime(int &time) |
|
1118 { |
|
1119 CX_DEBUG_ENTER_FUNCTION(); |
|
1120 |
|
1121 TTimeIntervalMicroSeconds timeElapsed = 0; |
|
1122 bool ok = false; |
|
1123 if (state() == CxeVideoCaptureControl::Recording) { |
|
1124 TRAPD( err, timeElapsed = mVideoRecorder->DurationL() ); |
|
1125 if (!err) { |
|
1126 time = timeElapsed.Int64() * 1.0 / KOneSecond; |
|
1127 CX_DEBUG(("timeElapsed2: %d", time)); |
|
1128 ok = true; |
|
1129 } |
|
1130 } |
|
1131 |
|
1132 CX_DEBUG_EXIT_FUNCTION(); |
|
1133 |
|
1134 return ok; |
|
1135 } |
|
1136 |
|
1137 /*! |
|
1138 * slot called when playing a sound has finished. |
|
1139 */ |
|
1140 void CxeVideoCaptureControlSymbian::handleSoundPlayed() |
|
1141 { |
|
1142 CX_DEBUG_ENTER_FUNCTION(); |
|
1143 |
|
1144 // start recording, if we were playing capture sound |
|
1145 if (state() == CxeVideoCaptureControl::PlayingStartSound) { |
|
1146 setState(CxeVideoCaptureControl::Recording); |
|
1147 mVideoRecorder->Record(); |
|
1148 } |
|
1149 |
|
1150 // in case of video capture stop sound playing, nothing needs to be done |
|
1151 // meaning the state set elsewhere, and the video capture has been stopped already |
|
1152 |
|
1153 CX_DEBUG_EXIT_FUNCTION(); |
|
1154 } |
|
1155 |
|
1156 |
|
1157 /*! |
|
1158 * setting has changed, check if we are interested. |
|
1159 */ |
|
1160 void CxeVideoCaptureControlSymbian::handleSettingValueChanged(const QString& settingId, |
|
1161 QVariant newValue) |
|
1162 { |
|
1163 CX_DEBUG_ENTER_FUNCTION(); |
|
1164 Q_UNUSED(newValue); |
|
1165 |
|
1166 if (mCameraDeviceControl.mode() == Cxe::VideoMode) { |
|
1167 if (settingId == CxeSettingIds::VIDEO_QUALITY) { |
|
1168 // re-prepare for video |
|
1169 if (state() == Ready) { |
|
1170 // release resources |
|
1171 deinit(); |
|
1172 // initialize video recording again |
|
1173 init(); |
|
1174 } |
|
1175 } else if (settingId == CxeSettingIds::VIDEO_MUTE_SETTING) { |
|
1176 // mute setting changed, apply the new setting and re-prepare. |
|
1177 setState(Preparing); |
|
1178 prepare(); |
|
1179 } else { |
|
1180 // Setting not relevant to video mode |
|
1181 } |
|
1182 } |
|
1183 |
|
1184 CX_DEBUG_EXIT_FUNCTION(); |
|
1185 } |
|
1186 |
|
1187 |
|
1188 /*! |
|
1189 * Returns QList of all supported video quality details based on the camera index |
|
1190 * (primary/secondary). |
|
1191 */ |
|
1192 QList<CxeVideoDetails> CxeVideoCaptureControlSymbian::supportedVideoQualities() |
|
1193 { |
|
1194 // update the remaining time counters for each quality setting |
|
1195 updateRemainingRecordingTimeCounter(); |
|
1196 return mIcmSupportedVideoResolutions; |
|
1197 } |
|
1198 |
|
1199 // End of file |