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 |
100 qRegisterMetaType<CxeVideoCaptureControl::State> (); |
91 qRegisterMetaType<CxeVideoCaptureControl::State> (); |
101 initializeStates(); |
92 initializeStates(); |
102 |
93 |
103 mVideoStopSoundPlayer = new |
94 mVideoStopSoundPlayer = new |
104 CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStop); |
95 CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStop, |
|
96 mSettings); |
105 mVideoStartSoundPlayer = new |
97 mVideoStartSoundPlayer = new |
106 CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStart); |
98 CxeSoundPlayerSymbian(CxeSoundPlayerSymbian::VideoCaptureStart, |
|
99 mSettings); |
107 |
100 |
108 // If camera is already allocated, call the slot ourselves. |
101 // If camera is already allocated, call the slot ourselves. |
109 if (mCameraDevice.camera()) { |
102 if (mCameraDevice.camera()) { |
110 handleCameraAllocated(CxeError::None); |
103 handleCameraAllocated(CxeError::None); |
111 } |
104 } |
116 this, SLOT(prepareForCameraDelete())); |
109 this, SLOT(prepareForCameraDelete())); |
117 connect(&cameraDevice, SIGNAL(prepareForRelease()), |
110 connect(&cameraDevice, SIGNAL(prepareForRelease()), |
118 this, SLOT(prepareForRelease()) ); |
111 this, SLOT(prepareForRelease()) ); |
119 connect(&cameraDevice, SIGNAL(cameraAllocated(CxeError::Id)), |
112 connect(&cameraDevice, SIGNAL(cameraAllocated(CxeError::Id)), |
120 this, SLOT(handleCameraAllocated(CxeError::Id))); |
113 this, SLOT(handleCameraAllocated(CxeError::Id))); |
|
114 |
121 // connect playing sound signals |
115 // connect playing sound signals |
122 connect(mVideoStartSoundPlayer, SIGNAL(playComplete(int)), |
116 connect(mVideoStartSoundPlayer, SIGNAL(playComplete(int)), |
123 this, SLOT(handleSoundPlayed())); |
117 this, SLOT(handleSoundPlayed())); |
124 |
118 |
|
119 // connect snapshot ready signal |
|
120 connect(&mSnapshotControl, SIGNAL(snapshotReady(CxeError::Id, const QImage&)), |
|
121 this, SLOT(handleSnapshotReady(CxeError::Id, const QImage&))); |
|
122 |
125 // enabling setting change callbacks to videocapturecontrol |
123 // enabling setting change callbacks to videocapturecontrol |
126 connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)), |
124 connect(&mSettings, SIGNAL(settingValueChanged(const QString&,QVariant)), |
127 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
125 this, SLOT(handleSettingValueChanged(const QString&,QVariant))); |
128 |
126 connect(&mSettings, SIGNAL(sceneChanged(CxeScene&)), |
129 connect(&mSettings, SIGNAL(sceneChanged(CxeScene&)), this, SLOT(handleSceneChanged(CxeScene&))); |
127 this, SLOT(handleSceneChanged(CxeScene&))); |
130 |
|
131 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_M2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
128 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_M2, "msg: e_CX_ENGINE_CONNECT_SIGNALS 0"); |
132 |
129 |
133 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 0"); |
130 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_CREATE_OUT, "msg: e_CX_VIDEOCAPTURECONTROL_NEW 0"); |
134 CX_DEBUG_EXIT_FUNCTION(); |
131 CX_DEBUG_EXIT_FUNCTION(); |
135 } |
132 } |
136 |
|
137 |
133 |
138 /*! |
134 /*! |
139 * CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
135 * CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
140 */ |
136 */ |
141 CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
137 CxeVideoCaptureControlSymbian::~CxeVideoCaptureControlSymbian() |
166 // video recorder already initalized. Continue to prepare video reocording. |
161 // video recorder already initalized. Continue to prepare video reocording. |
167 open(); |
162 open(); |
168 } |
163 } |
169 |
164 |
170 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 0" ); |
165 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_INIT, "msg: e_CX_VIDEO_CAPCONT_INIT 0" ); |
171 |
166 CX_DEBUG_EXIT_FUNCTION(); |
172 CX_DEBUG_EXIT_FUNCTION(); |
167 } |
173 } |
168 |
174 |
169 /*! |
175 |
|
176 /* |
|
177 * Releases all resources |
170 * Releases all resources |
178 */ |
171 */ |
179 void CxeVideoCaptureControlSymbian::deinit() |
172 void CxeVideoCaptureControlSymbian::deinit() |
180 { |
173 { |
181 CX_DEBUG_ENTER_FUNCTION(); |
174 CX_DEBUG_ENTER_FUNCTION(); |
182 |
175 |
183 if(state() == Idle) { |
176 // Nothing to do if already idle. |
184 // nothing to do |
177 if(state() != Idle) { |
185 return; |
178 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" ); |
186 } |
179 |
187 |
180 // first stop viewfinder |
188 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 1" ); |
181 mViewfinderControl.stop(); |
189 |
182 |
190 // first stop viewfinder |
183 // stop video-recording in-case if its ongoing. |
191 mViewfinderControl.stop(); |
184 stop(); |
192 |
185 |
193 // stop video-recording in-case if its ongoing. |
186 // Check if state is stopping, in which case we have to inform the |
194 stop(); |
187 // file harvester that a file is to be completed. We would not |
195 |
188 // call harvestFile otherwise in this case. |
196 if (mCameraDevice.cameraSnapshot()) { |
189 // Otherwise the video will not be found from videos app. |
197 mCameraDevice.cameraSnapshot()->StopSnapshot(); |
190 if (state() == Stopping) { |
198 } |
191 emit videoComposed(CxeError::None, mCurrentFilename); |
199 |
192 } |
200 if (mVideoRecorder) { |
193 |
201 mVideoRecorder->Close(); |
194 mSnapshotControl.stop(); |
202 } |
195 |
203 |
196 if (mVideoRecorder) { |
204 // revert back the new filename to empty string so that we generate a new file name |
197 mVideoRecorder->close(); |
205 // when we init again |
198 } |
206 mNewFileName = QString(""); |
199 |
207 |
200 setState(Idle); |
208 setState(Idle); |
201 |
209 |
202 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" ); |
210 OstTrace0( camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_DEINIT, "msg: e_CX_VIDEO_CAPCONT_DEINIT 0" ); |
203 } |
211 |
204 CX_DEBUG_EXIT_FUNCTION(); |
212 CX_DEBUG_EXIT_FUNCTION(); |
205 } |
213 } |
|
214 |
|
215 |
206 |
216 /*! |
207 /*! |
217 * Intializes VideoRecorder for recording. |
208 * Intializes VideoRecorder for recording. |
218 */ |
209 */ |
219 void CxeVideoCaptureControlSymbian::initVideoRecorder() |
210 void CxeVideoCaptureControlSymbian::initVideoRecorder() |
220 { |
211 { |
221 CX_DEBUG_ENTER_FUNCTION(); |
212 CX_DEBUG_ENTER_FUNCTION(); |
222 |
213 |
223 if (state() != Idle) { |
214 // Init needed only in Idle state |
224 // not valid state to start "open" operation |
215 if (state() == Idle) { |
225 return; |
216 try { |
226 } |
217 // if video recorder is not created, do it now. |
227 |
218 createVideoRecorder(); |
228 if(!mVideoRecorder) { |
219 |
229 // if video recorder is not created, do it now. |
220 // update current video quality details from icm. |
230 createVideoRecorder(); |
221 // Throws an error if unable to get the quality. |
231 } |
222 getVideoQualityDetails(mCurrentVideoDetails); |
232 |
223 |
233 // update current video quality details from icm |
224 // 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); |
225 setState(Initialized); |
252 open(); |
226 open(); |
253 } |
227 } catch (const std::exception &e) { |
254 } else { |
228 // Handle error |
255 err = CxeErrorHandlingSymbian::map(KErrNotReady); |
229 handlePrepareFailed(); |
256 } |
230 } |
257 |
231 } |
258 if (err) { |
232 |
259 // In case of error |
233 CX_DEBUG_EXIT_FUNCTION(); |
260 emit videoPrepareComplete(err); |
234 } |
261 deinit(); |
|
262 } |
|
263 |
|
264 CX_DEBUG_EXIT_FUNCTION(); |
|
265 } |
|
266 |
|
267 |
|
268 |
235 |
269 /*! |
236 /*! |
270 * Opens file for video recording. |
237 * Opens file for video recording. |
271 */ |
238 */ |
272 void CxeVideoCaptureControlSymbian::open() |
239 void CxeVideoCaptureControlSymbian::open() |
273 { |
240 { |
274 CX_DEBUG_ENTER_FUNCTION(); |
241 CX_DEBUG_ENTER_FUNCTION(); |
275 |
242 |
276 if (state() != Initialized) { |
243 // Check valid state to start "open" operation |
277 // not valid state to start "open" operation |
244 if (state() == Initialized) { |
278 return; |
245 try { |
279 } |
246 // generate video file name, if necessary |
280 |
247 generateFilename(); |
281 CxeError::Id err = CxeError::None; |
248 CX_DEBUG(( "Next video file path: %s", mCurrentFilename.toAscii().constData() )); |
282 |
249 |
283 // generate video file name, if necessary |
250 // Start preparing.. |
284 if (mNewFileName.isEmpty()) { |
251 setState(CxeVideoCaptureControl::Preparing); |
285 QStringList list = mCurrentVideoDetails.mVideoFileMimeType.split("/"); |
252 |
286 QString fileExt("."); |
253 // Exception thrown if open fails. |
287 if (list.count() == 2) { |
254 mVideoRecorder->open(mCameraDevice.camera()->Handle(), |
288 fileExt = fileExt + list[1]; |
255 mCurrentFilename, |
289 } |
256 mCurrentVideoDetails.mVideoFileMimeType, |
290 // Generate new filename and open the file for writing video data |
257 mCurrentVideoDetails.mPreferredSupplier, |
291 err = mFilenameGenerator.generateFilename(mNewFileName, fileExt); |
258 mCurrentVideoDetails.mVideoCodecMimeType, |
292 if (err == CxeError::None) { |
259 mCurrentVideoDetails.mAudioType); |
293 mCurrentFilename = mNewFileName; |
260 } catch (const std::exception &e) { |
294 } else { |
261 handlePrepareFailed(); |
295 // file name is not valid, re-initialize the value of current string |
262 } |
296 // back to empty string |
263 } |
297 mCurrentFilename = QString(""); |
264 CX_DEBUG_EXIT_FUNCTION(); |
298 } |
265 } |
299 } |
266 |
300 |
267 /*! |
301 if (!err && |
268 * Helper method for generating filename. |
302 mVideoRecorder && |
269 * Throws exception, if file type mime is formatted wrong or |
303 !mCurrentFilename.isEmpty()) { |
270 * filename generation fails. |
304 |
271 */ |
305 TPtrC16 fName(reinterpret_cast<const TUint16*>(mCurrentFilename.utf16())); |
272 void CxeVideoCaptureControlSymbian::generateFilename() |
306 CX_DEBUG(( "Next video file path: %s", mCurrentFilename.toAscii().constData() )); |
273 { |
307 |
274 CX_DEBUG_ENTER_FUNCTION(); |
308 // read video codec mime type |
275 mCurrentFilename = QString(""); |
309 QByteArray videoCodecData = |
276 |
310 mCurrentVideoDetails.mVideoCodecMimeType.toLatin1(); |
277 QStringList list = mCurrentVideoDetails.mVideoFileMimeType.split("/"); |
311 TPtrC8 videoCodecMimeType(reinterpret_cast<const TUint8*> |
278 // Throw exception if mime string is formatted wrong. |
312 (videoCodecData.constData()), videoCodecData.size()); |
279 if (list.count() != 2) { |
313 |
280 throw new CxeException(CxeError::General); |
314 setState(CxeVideoCaptureControl::Preparing); |
281 } |
315 |
282 QString fileExt = "." + list[1]; |
316 TRAPD(openErr, mVideoRecorder->OpenFileL(fName, |
283 |
317 mCameraDevice.camera()->Handle(), |
284 // Generate new filename and open the file for writing video data |
318 mVideoControllerUid, |
285 CxeException::throwIfError(mFilenameGenerator.generateFilename(mCurrentFilename, fileExt)); |
319 mVideoFormatUid, |
286 |
320 videoCodecMimeType, |
287 CX_DEBUG_EXIT_FUNCTION(); |
321 audioType(mCurrentVideoDetails.mAudioType))); |
288 } |
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 |
289 |
362 /*! |
290 /*! |
363 * Prepare Video Recorder with necessary settings for video capture. |
291 * Prepare Video Recorder with necessary settings for video capture. |
364 */ |
292 */ |
365 void CxeVideoCaptureControlSymbian::prepare() |
293 void CxeVideoCaptureControlSymbian::prepare() |
388 mSettings.get(CxeSettingIds::FRAME_RATE, frameRate); |
311 mSettings.get(CxeSettingIds::FRAME_RATE, frameRate); |
389 if (frameRate <= 0) { |
312 if (frameRate <= 0) { |
390 frameRate = mCurrentVideoDetails.mVideoFrameRate; |
313 frameRate = mCurrentVideoDetails.mVideoFrameRate; |
391 } |
314 } |
392 |
315 |
|
316 CX_DEBUG(("Video resolution (%d,%d)", mCurrentVideoDetails.mWidth, |
|
317 mCurrentVideoDetails.mHeight)); |
|
318 CX_DEBUG(("Video bitrate = %d)", mCurrentVideoDetails.mVideoBitRate)); |
393 CX_DEBUG(("Video frame rate = %d)", frameRate)); |
319 CX_DEBUG(("Video frame rate = %d)", frameRate)); |
394 |
320 |
395 TRAPD(err, |
321 try { |
396 { |
322 mVideoRecorder->setVideoFrameSize(frameSize); |
397 mVideoRecorder->SetVideoFrameSizeL(frameSize); |
323 mVideoRecorder->setVideoFrameRate(frameRate); |
398 mVideoRecorder->SetVideoFrameRateL(frameRate); |
324 mVideoRecorder->setVideoBitRate(mCurrentVideoDetails.mVideoBitRate); |
399 mVideoRecorder->SetVideoBitRateL(mCurrentVideoDetails.mVideoBitRate); |
325 mVideoRecorder->setAudioEnabled(muteSetting == 0); |
400 mVideoRecorder->SetAudioEnabledL(muteSetting == 0); |
326 // "No limit" value is handled in video recorder wrapper. |
401 // "No limit" value is handled in video recorder wrapper. |
327 mVideoRecorder->setVideoMaxSize(mCurrentVideoDetails.mMaximumSizeInBytes); |
402 mVideoRecorder->SetMaxClipSizeL(mCurrentVideoDetails.mMaximumSizeInBytes); |
328 |
403 } |
329 // Settings have been applied successfully, start to prepare. |
404 ); |
330 mVideoRecorder->prepare(); |
405 |
331 |
406 if (!err) { |
332 // Prepare snapshot. Snapshot control throws error if problems. |
407 // settings have been applied successfully, start to prepare |
333 QSize snapshotSize = mSnapshotControl.calculateSnapshotSize( |
408 mVideoRecorder->Prepare(); |
334 mViewfinderControl.deviceDisplayResolution(), |
409 // prepare snapshot |
335 mCurrentVideoDetails.mAspectRatio); |
410 err = prepareVideoSnapshot(); |
336 mSnapshotControl.start(snapshotSize); |
411 } |
337 |
412 |
338 // 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(); |
339 emit prepareZoomForVideo(); |
416 } |
340 emit videoPrepareComplete(CxeError::None); |
417 // emit video prepare status |
341 } catch (const std::exception &e) { |
418 emit videoPrepareComplete(CxeErrorHandlingSymbian::map(err)); |
342 // Handle error. |
419 |
343 handlePrepareFailed(); |
420 OstTrace0(camerax_performance, DUP1_CXEVIDEOCAPTURECONTROLSYMBIAN_PREPARE, "msg: e_CX_VIDCAPCONT_PREPARE 0"); |
344 } |
421 |
345 |
422 CX_DEBUG_EXIT_FUNCTION(); |
346 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_PREPARE_2, "msg: e_CX_VIDCAPCONT_PREPARE 0"); |
423 } |
347 CX_DEBUG_EXIT_FUNCTION(); |
424 |
348 } |
425 |
349 |
426 |
350 /*! |
427 /*! |
351 * Fetches video qualites details based on video quality setting. |
428 Fetches video qualites details based on video quality setting. |
352 */ |
429 Returns CxeError codes if any. |
353 void |
430 */ |
|
431 CxeError::Id |
|
432 CxeVideoCaptureControlSymbian::getVideoQualityDetails(CxeVideoDetails &videoInfo) |
354 CxeVideoCaptureControlSymbian::getVideoQualityDetails(CxeVideoDetails &videoInfo) |
433 { |
355 { |
434 CX_DEBUG_ENTER_FUNCTION(); |
356 CX_DEBUG_ENTER_FUNCTION(); |
435 |
357 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROL_GETQUALITYDETAILS_1, "msg: e_CX_GET_QUALITY_DETAILS 1" ); |
436 int videoQuality = 0; |
358 |
437 CxeError::Id err = CxeError::None; |
359 int quality(0); |
438 |
360 |
|
361 // Get quality index for primary camera. Only one quality for secondary camera. |
439 if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { |
362 if (mCameraDeviceControl.cameraIndex() == Cxe::PrimaryCameraIndex) { |
440 err = mSettings.get(CxeSettingIds::VIDEO_QUALITY, videoQuality); |
363 CxeException::throwIfError(mSettings.get(CxeSettingIds::VIDEO_QUALITY, quality)); |
441 |
364 } |
442 bool validQuality = (videoQuality >= 0 && |
365 |
443 videoQuality < mIcmSupportedVideoResolutions.count()); |
366 if (quality < 0 || quality >= mIcmSupportedVideoResolutions.count()) { |
444 if (err == CxeError::None && validQuality) { |
367 throw new CxeException(CxeError::NotFound); |
445 // get video quality details |
368 } |
446 videoInfo = mIcmSupportedVideoResolutions.at(videoQuality); |
369 |
447 } else { |
370 // get video quality details |
448 // not valid video quality |
371 videoInfo = mIcmSupportedVideoResolutions.at(quality); |
449 err = CxeError::NotFound; |
372 |
450 } |
373 OstTrace0( camerax_performance, CXEVIDEOCAPTURECONTROL_GETQUALITYDETAILS_2, "msg: e_CX_GET_QUALITY_DETAILS 0" ); |
451 } else { |
374 CX_DEBUG_EXIT_FUNCTION(); |
452 // get secondary camera video quality index |
375 } |
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 |
376 |
614 /*! |
377 /*! |
615 * Resets the video snapshot and current video filename |
378 * Resets the video snapshot and current video filename |
616 */ |
379 */ |
617 void CxeVideoCaptureControlSymbian::reset() |
380 void CxeVideoCaptureControlSymbian::reset() |
699 |
452 |
700 if (state() == Recording || state() == Paused) { |
453 if (state() == Recording || state() == Paused) { |
701 // first stop viewfinder |
454 // first stop viewfinder |
702 mViewfinderControl.stop(); |
455 mViewfinderControl.stop(); |
703 |
456 |
704 TInt asyncStopErr = mVideoRecorder->CustomCommandSync( |
457 try { |
705 TMMFMessageDestination(KCamCControllerImplementationUid, |
458 // Try asynchronous stopping first. |
706 KMMFObjectHandleController), |
459 mVideoRecorder->stop(true); |
707 ECamCControllerCCVideoStopAsync, |
460 // No error from asynchronous stop -> wait for stop event |
708 KNullDesC8, |
461 setState(Stopping); |
709 KNullDesC8 ); |
462 } catch (const std::exception &e) { |
710 CX_DEBUG(("ECamCControllerCCVideoStopAsync sent, err=%d", asyncStopErr)); |
463 CX_DEBUG(("CxeVideoCaptureControlSymbian - async stop failed, try sync..")); |
711 if (asyncStopErr) { // fall back to synchronous stop |
464 try { |
712 TInt syncStopErr = mVideoRecorder->Stop(); |
465 mVideoRecorder->stop(false); |
713 if (syncStopErr) { |
466 // stopping went ok |
714 // error during stop operation, release resources |
467 emulateNormalStopping(); |
715 emit videoComposed(CxeErrorHandlingSymbian::map(asyncStopErr), filename()); |
468 } catch (const std::exception &e) { |
716 deinit(); |
469 // Even synchronous stopping failed -> release resources. |
717 } else { |
470 CX_DEBUG(("CxeVideoCaptureControlSymbian - sync stop failed, too!")); |
718 // stop operation went fine, set back the state to Initialized. |
471 handleComposeFailed(qt_symbian_exception2Error(e)); |
719 setState(Initialized); |
|
720 mFilenameGenerator.raiseCounterValue(); |
|
721 } |
472 } |
|
473 } |
|
474 } |
|
475 |
|
476 CX_DEBUG_EXIT_FUNCTION(); |
|
477 } |
|
478 |
|
479 /*! |
|
480 * Callback when "Open" operation is complete. |
|
481 */ |
|
482 void CxeVideoCaptureControlSymbian::MvruoOpenComplete(TInt aError) |
|
483 { |
|
484 CX_DEBUG_ENTER_FUNCTION(); |
|
485 CX_DEBUG(("CxeVideoCaptureControlSymbian::MvruoOpenComplete, err=%d", aError)); |
|
486 |
|
487 if (state() == Preparing) { |
|
488 if (!aError) { |
|
489 prepare(); |
722 } else { |
490 } else { |
723 // No error from asynch stop custom command... wait for stop event |
491 handlePrepareFailed(); |
724 setState(Stopping); |
492 } |
725 mFilenameGenerator.raiseCounterValue(); |
493 } |
726 } |
494 |
727 } |
495 CX_DEBUG_EXIT_FUNCTION(); |
728 |
496 } |
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 |
497 |
756 /*! |
498 /*! |
757 * Callback when "Prepare" request is complete. |
499 * Callback when "Prepare" request is complete. |
758 */ |
500 */ |
759 void CxeVideoCaptureControlSymbian::MvruoPrepareComplete(TInt aError) |
501 void CxeVideoCaptureControlSymbian::MvruoPrepareComplete(TInt aError) |
822 CX_DEBUG(("KCamCControllerCCVideoFileComposed")); |
556 CX_DEBUG(("KCamCControllerCCVideoFileComposed")); |
823 if (state() == Stopping) { |
557 if (state() == Stopping) { |
824 // stop operation went fine, set back the state to intialized. |
558 // stop operation went fine, set back the state to intialized. |
825 setState(Initialized); |
559 setState(Initialized); |
826 } |
560 } |
|
561 mFilenameGenerator.raiseCounterValue(); |
827 // video file has composed, everything went well, inform the client |
562 // video file has composed, everything went well, inform the client |
828 emit videoComposed(CxeError::None, filename()); |
563 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 { |
564 } else { |
833 CX_DEBUG(("ignoring unknown MvruoEvent 0x%08x", aEvent.iEventType.iUid )); |
565 CX_DEBUG(("ignoring unknown MvruoEvent 0x%08x", aEvent.iEventType.iUid )); |
834 } |
566 } |
835 |
567 |
836 CX_DEBUG_EXIT_FUNCTION(); |
568 CX_DEBUG_EXIT_FUNCTION(); |
837 } |
569 } |
838 |
570 |
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 /*! |
571 /*! |
919 * camera reference changing, release resources |
572 * camera reference changing, release resources |
920 */ |
573 */ |
921 void CxeVideoCaptureControlSymbian::prepareForCameraDelete() |
574 void CxeVideoCaptureControlSymbian::prepareForCameraDelete() |
922 { |
575 { |
933 CX_DEBUG_ENTER_FUNCTION(); |
586 CX_DEBUG_ENTER_FUNCTION(); |
934 deinit(); |
587 deinit(); |
935 CX_DEBUG_EXIT_FUNCTION(); |
588 CX_DEBUG_EXIT_FUNCTION(); |
936 } |
589 } |
937 |
590 |
938 |
591 /*! |
939 /*! |
592 * new camera available |
940 * new camera available, |
|
941 */ |
593 */ |
942 void CxeVideoCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) |
594 void CxeVideoCaptureControlSymbian::handleCameraAllocated(CxeError::Id error) |
943 { |
595 { |
944 CX_DEBUG_ENTER_FUNCTION(); |
596 CX_DEBUG_ENTER_FUNCTION(); |
945 |
597 |
946 if (!error) { |
598 if (!error) { |
947 // initialize the video recorder utility |
599 try { |
948 createVideoRecorder(); |
600 // Create the video recorder utility |
|
601 createVideoRecorder(); |
|
602 } catch (...) { |
|
603 // We are just trying to create the recorder early. |
|
604 // Retry later when preparing, and fail then if |
|
605 // error still persists. |
|
606 } |
949 // new camera available, read supported video qualities from icm |
607 // new camera available, read supported video qualities from icm |
950 // load all still qualities supported by icm |
608 // load all video qualities supported by icm |
951 mIcmSupportedVideoResolutions.clear(); |
609 mIcmSupportedVideoResolutions.clear(); |
952 Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex(); |
610 Cxe::CameraIndex cameraIndex = mCameraDeviceControl.cameraIndex(); |
953 // get list of supported image qualities based on camera index |
611 // get list of supported image qualities based on camera index |
954 mIcmSupportedVideoResolutions = |
612 mIcmSupportedVideoResolutions = |
955 mQualityPresets.videoQualityPresets(cameraIndex); |
613 mQualityPresets.videoQualityPresets(cameraIndex); |
956 } |
614 } |
957 |
615 |
958 CX_DEBUG_EXIT_FUNCTION(); |
616 CX_DEBUG_EXIT_FUNCTION(); |
959 } |
617 } |
960 |
618 |
961 |
|
962 /*! |
619 /*! |
963 * Initializes video recorder. |
620 * Initializes video recorder. |
|
621 * May throw exception. |
964 */ |
622 */ |
965 void CxeVideoCaptureControlSymbian::createVideoRecorder() |
623 void CxeVideoCaptureControlSymbian::createVideoRecorder() |
966 { |
624 { |
967 CX_DEBUG_ENTER_FUNCTION(); |
625 CX_DEBUG_ENTER_FUNCTION(); |
968 |
626 if (mVideoRecorder == NULL) { |
969 // init video recoder |
627 mVideoRecorder = new CxeVideoRecorderUtilitySymbian(*this); |
970 if (state() == CxeVideoCaptureControl::Idle) { |
628 } |
971 if (mVideoRecorder == NULL) { |
629 CX_DEBUG_EXIT_FUNCTION(); |
972 TRAPD(initErr, mVideoRecorder = |
630 } |
973 new CxeVideoRecorderUtilitySymbian( *this , |
631 |
974 KAudioPriorityVideoRecording, |
632 /*! |
975 TMdaPriorityPreference( KAudioPrefVideoRecording ))); |
633 * 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 */ |
634 */ |
990 void CxeVideoCaptureControlSymbian::releaseResources() |
635 void CxeVideoCaptureControlSymbian::releaseResources() |
991 { |
636 { |
992 CX_DEBUG_ENTER_FUNCTION(); |
637 CX_DEBUG_ENTER_FUNCTION(); |
993 |
|
994 // Save the state and filename before releasing. |
|
995 QString filenameCopy(filename()); |
|
996 CxeVideoCaptureControl::State stateCopy(state()); |
|
997 |
638 |
998 // first de-init videocapture control |
639 // first de-init videocapture control |
999 deinit(); |
640 deinit(); |
1000 reset(); |
641 reset(); |
1001 |
642 |
1002 // Check if state is stopping, in which case we have to inform the |
|
1003 // file harvester that a file is to be completed. We would not |
|
1004 // call harvestFile otherwise in this case. |
|
1005 // Otherwise the video will not be found from videos app. |
|
1006 if (stateCopy == CxeVideoCaptureControl::Stopping) { |
|
1007 emit videoComposed(CxeError::None, filenameCopy); |
|
1008 } |
|
1009 |
|
1010 delete mVideoRecorder; |
643 delete mVideoRecorder; |
1011 mVideoRecorder = NULL; |
644 mVideoRecorder = NULL; |
1012 |
645 |
1013 CX_DEBUG_EXIT_FUNCTION(); |
646 CX_DEBUG_EXIT_FUNCTION(); |
1014 } |
647 } |
1015 |
648 |
1016 |
649 /*! |
1017 /*! |
650 * Returns current state of video capture control |
1018 Returns current state of videocapture |
|
1019 */ |
651 */ |
1020 CxeVideoCaptureControl::State CxeVideoCaptureControlSymbian::state() const |
652 CxeVideoCaptureControl::State CxeVideoCaptureControlSymbian::state() const |
1021 { |
653 { |
1022 return static_cast<CxeVideoCaptureControl::State> (stateId()); |
654 return static_cast<CxeVideoCaptureControl::State> (stateId()); |
1023 } |
655 } |
1024 |
656 |
1025 |
657 /*! |
1026 /*! |
658 * Called when state is changed. |
1027 * slot called when state is changed. |
|
1028 */ |
659 */ |
1029 void CxeVideoCaptureControlSymbian::handleStateChanged(int newStateId, CxeError::Id error) |
660 void CxeVideoCaptureControlSymbian::handleStateChanged(int newStateId, CxeError::Id error) |
1030 { |
661 { |
1031 switch (newStateId) { |
662 switch (newStateId) { |
1032 case Ready: |
663 case Ready: |
1076 { |
705 { |
1077 CX_DEBUG_ENTER_FUNCTION(); |
706 CX_DEBUG_ENTER_FUNCTION(); |
1078 |
707 |
1079 for( int index = 0; index < mIcmSupportedVideoResolutions.count(); index++) { |
708 for( int index = 0; index < mIcmSupportedVideoResolutions.count(); index++) { |
1080 CxeVideoDetails &qualityDetails = mIcmSupportedVideoResolutions[index]; |
709 CxeVideoDetails &qualityDetails = mIcmSupportedVideoResolutions[index]; |
1081 calculateRemainingTime(qualityDetails, qualityDetails.mRemainingTime); |
710 qualityDetails.mRemainingTime = calculateRemainingTime(qualityDetails); |
1082 } |
711 } |
1083 |
712 |
1084 CX_DEBUG_EXIT_FUNCTION(); |
713 CX_DEBUG_EXIT_FUNCTION(); |
1085 } |
714 } |
1086 |
715 |
1087 /* |
716 /*! |
1088 * calculates remaining video recording time. |
717 * calculates remaining video recording time. |
1089 */ |
718 */ |
1090 void CxeVideoCaptureControlSymbian::remainingTime(int &time) |
719 void CxeVideoCaptureControlSymbian::remainingTime(int &time) |
1091 { |
720 { |
1092 CX_DEBUG_ENTER_FUNCTION(); |
721 CX_DEBUG_ENTER_FUNCTION(); |
1093 |
722 |
1094 if (state() == CxeVideoCaptureControl::Recording || |
723 if (state() == CxeVideoCaptureControl::Recording || |
1095 state() == CxeVideoCaptureControl::Paused) { |
724 state() == CxeVideoCaptureControl::Paused) { |
1096 TTimeIntervalMicroSeconds remaining = 0; |
725 time = mVideoRecorder->availableRecordingTime(); |
1097 remaining = mVideoRecorder->RecordTimeAvailable(); |
726 CX_DEBUG(("CxeVideoCaptureControlSymbian - time remaining: %d", time)); |
1098 time = remaining.Int64() * 1.0 / KOneSecond; |
|
1099 CX_DEBUG(( "timeRemaining2: %d", time )); |
|
1100 } else { |
727 } else { |
1101 // Check if we need to recalculate the remaining time. |
728 // Check if we need to recalculate the remaining time. |
1102 if (mCurrentVideoDetails.mRemainingTime == CxeVideoDetails::UNKNOWN) { |
729 if (mCurrentVideoDetails.mRemainingTime == CxeVideoDetails::UNKNOWN) { |
1103 calculateRemainingTime(mCurrentVideoDetails, mCurrentVideoDetails.mRemainingTime); |
730 mCurrentVideoDetails.mRemainingTime = calculateRemainingTime(mCurrentVideoDetails); |
1104 } |
731 } |
1105 time = mCurrentVideoDetails.mRemainingTime; |
732 time = mCurrentVideoDetails.mRemainingTime; |
1106 } |
733 } |
1107 |
734 |
1108 CX_DEBUG_EXIT_FUNCTION(); |
735 CX_DEBUG_EXIT_FUNCTION(); |
1109 } |
736 } |
1110 |
737 |
1111 |
738 /*! |
1112 |
739 * Get the remaining recording time |
1113 /*! |
740 * @param videoDetails Contains the current video resolution that is in use. |
1114 * algorithm to calculate remaining recording time |
741 * @return The remaining recording time |
1115 @ param videoDetails contains the current video resolution that is in use. |
742 */ |
1116 @ time contains the remaining recording time |
743 int CxeVideoCaptureControlSymbian::calculateRemainingTime(const CxeVideoDetails& videoDetails) |
1117 */ |
744 { |
1118 void CxeVideoCaptureControlSymbian::calculateRemainingTime(CxeVideoDetails videoDetails, int &time) |
745 CX_DEBUG_ENTER_FUNCTION(); |
1119 { |
746 qint64 availableSpace = mDiskMonitor.free() - KMinRequiredSpaceVideo; |
1120 CX_DEBUG_ENTER_FUNCTION(); |
747 int time = mQualityPresets.recordingTimeAvailable(videoDetails, availableSpace); |
1121 |
748 CX_DEBUG_EXIT_FUNCTION(); |
1122 TTimeIntervalMicroSeconds remaining = 0; |
749 return time; |
1123 |
750 } |
1124 // get available space in the drive selected in the settings |
751 |
1125 // for storing videos |
752 /*! |
1126 qint64 availableSpace = mDiskMonitor.free(); |
753 * Calculates elapsed recording time during video recording |
1127 |
754 * @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 */ |
755 */ |
1186 bool CxeVideoCaptureControlSymbian::elapsedTime(int &time) |
756 bool CxeVideoCaptureControlSymbian::elapsedTime(int &time) |
1187 { |
757 { |
1188 CX_DEBUG_ENTER_FUNCTION(); |
758 CX_DEBUG_ENTER_FUNCTION(); |
1189 |
759 |
1190 TTimeIntervalMicroSeconds timeElapsed = 0; |
|
1191 bool ok = false; |
760 bool ok = false; |
1192 if (state() == CxeVideoCaptureControl::Recording || |
761 if (state() == CxeVideoCaptureControl::Recording || |
1193 state() == CxeVideoCaptureControl::Paused) { |
762 state() == CxeVideoCaptureControl::Paused) { |
1194 TRAPD( err, timeElapsed = mVideoRecorder->DurationL() ); |
763 try { |
1195 if (!err) { |
764 time = mVideoRecorder->duration(); |
1196 time = timeElapsed.Int64() * 1.0 / KOneSecond; |
765 CX_DEBUG(("CxeVideoCaptureControlSymbian - elapsed: %d", time)); |
1197 CX_DEBUG(("timeElapsed2: %d", time)); |
|
1198 ok = true; |
766 ok = true; |
1199 } |
767 } catch (const std::exception &e) { |
1200 } |
768 // Returning false. |
1201 |
769 } |
1202 CX_DEBUG_EXIT_FUNCTION(); |
770 } |
1203 |
771 |
|
772 CX_DEBUG_EXIT_FUNCTION(); |
1204 return ok; |
773 return ok; |
1205 } |
774 } |
1206 |
775 |
1207 /*! |
776 /*! |
1208 * slot called when playing a sound has finished. |
777 * slot called when playing a sound has finished. |
1212 CX_DEBUG_ENTER_FUNCTION(); |
781 CX_DEBUG_ENTER_FUNCTION(); |
1213 |
782 |
1214 // start recording, if we were playing capture sound |
783 // start recording, if we were playing capture sound |
1215 if (state() == CxeVideoCaptureControl::PlayingStartSound) { |
784 if (state() == CxeVideoCaptureControl::PlayingStartSound) { |
1216 setState(CxeVideoCaptureControl::Recording); |
785 setState(CxeVideoCaptureControl::Recording); |
1217 |
786 mVideoRecorder->record(); |
1218 mVideoRecorder->Record(); |
|
1219 } |
787 } |
1220 |
788 |
1221 // in case of video capture stop sound playing, nothing needs to be done |
789 // 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 |
790 // meaning the state set elsewhere, and the video capture has been stopped already |
1223 |
791 |
1224 CX_DEBUG_EXIT_FUNCTION(); |
792 CX_DEBUG_EXIT_FUNCTION(); |
1225 } |
793 } |
1226 |
794 |
|
795 /*! |
|
796 * Handle new snapshot. |
|
797 * @param status Status code for getting the snapshot. |
|
798 * @param snapshot Snapshot pixmap. Empty if error code reported. |
|
799 */ |
|
800 void CxeVideoCaptureControlSymbian::handleSnapshotReady(CxeError::Id status, const QImage &snapshot) |
|
801 { |
|
802 CX_DEBUG_ENTER_FUNCTION(); |
|
803 |
|
804 if (mCameraDeviceControl.mode() == Cxe::VideoMode) { |
|
805 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_HANDLESNAPSHOT_1, "msg: e_CX_HANDLE_SNAPSHOT 1"); |
|
806 |
|
807 // Need to store snapshot for ui to be able to get it also later. |
|
808 mSnapshot = QPixmap::fromImage(snapshot); |
|
809 emit snapshotReady(status, snapshot, filename()); |
|
810 |
|
811 OstTrace0(camerax_performance, CXEVIDEOCAPTURECONTROL_HANDLESNAPSHOT_2, "msg: e_CX_HANDLE_SNAPSHOT 0"); |
|
812 } |
|
813 |
|
814 CX_DEBUG_EXIT_FUNCTION(); |
|
815 } |
1227 |
816 |
1228 /*! |
817 /*! |
1229 * setting has changed, check if we are interested. |
818 * setting has changed, check if we are interested. |
1230 */ |
819 */ |
1231 void CxeVideoCaptureControlSymbian::handleSettingValueChanged(const QString& settingId, |
820 void CxeVideoCaptureControlSymbian::handleSettingValueChanged(const QString& settingId, |