@@ -147,115 +147,121 @@ class VideoCapturer(private val mActivity: MainActivity) {
147
147
return null
148
148
}
149
149
150
+ val startRecordingLock = Any ()
151
+
150
152
fun startRecording () {
151
- if (camConfig.camera == null ) return
152
- val recorder = camConfig.videoCapture?.output ? : return
153
+ synchronized(startRecordingLock) {
154
+ if (camConfig.camera == null ) return
155
+ val recorder = camConfig.videoCapture?.output ? : return
156
+ if (isRecording) return
157
+ isRecording = true
153
158
154
- val dateString = SimpleDateFormat (" yyyyMMdd_HHmmss" , Locale .US ).format(Date ())
155
- val fileName = VIDEO_NAME_PREFIX + dateString + videoFileFormat
159
+ val dateString = SimpleDateFormat (" yyyyMMdd_HHmmss" , Locale .US ).format(Date ())
160
+ val fileName = VIDEO_NAME_PREFIX + dateString + videoFileFormat
156
161
157
- includeAudio = false
162
+ includeAudio = false
158
163
159
- val ctx = mActivity
164
+ val ctx = mActivity
160
165
161
- if (ctx.settingsDialog.includeAudioToggle.isChecked) {
162
- if (ctx.checkSelfPermission(Manifest .permission.RECORD_AUDIO ) == PERMISSION_GRANTED ) {
163
- includeAudio = true
164
- } else {
165
- ctx.restartRecordingWithMicPermission()
166
- return
166
+ if (ctx.settingsDialog.includeAudioToggle.isChecked) {
167
+ if (ctx.checkSelfPermission(Manifest .permission.RECORD_AUDIO ) == PERMISSION_GRANTED ) {
168
+ includeAudio = true
169
+ } else {
170
+ ctx.restartRecordingWithMicPermission()
171
+ isRecording = false
172
+ return
173
+ }
167
174
}
168
- }
169
175
170
- val recordingCtx = try {
171
- createRecordingContext(recorder, fileName)!!
172
- } catch (exception: Exception ) {
173
- val foreignUri = ctx is VideoCaptureActivity && ctx.isOutputUriAvailable()
174
- if (! foreignUri) {
175
- camConfig.onStorageLocationNotFound()
176
+ val recordingCtx = try {
177
+ createRecordingContext(recorder, fileName)!!
178
+ } catch (exception: Exception ) {
179
+ val foreignUri = ctx is VideoCaptureActivity && ctx.isOutputUriAvailable()
180
+ if (! foreignUri) {
181
+ camConfig.onStorageLocationNotFound()
182
+ }
183
+ ctx.showMessage(R .string.unable_to_access_output_file)
184
+ isRecording = false
185
+ return
176
186
}
177
- ctx.showMessage(R .string.unable_to_access_output_file)
178
- return
179
- }
180
187
181
- val pendingRecording = recordingCtx.pendingRecording
182
-
183
- if (includeAudio) {
184
- pendingRecording.withAudioEnabled()
185
- }
188
+ val pendingRecording = recordingCtx.pendingRecording
186
189
187
- beforeRecordingStarts()
188
-
189
- isRecording = true
190
+ if (includeAudio) {
191
+ pendingRecording.withAudioEnabled()
192
+ }
190
193
191
- camConfig.mPlayer.playVRStartSound(handler) {
194
+ beforeRecordingStarts()
192
195
193
- recording = pendingRecording.start(ctx.mainExecutor ) { event ->
196
+ camConfig.mPlayer.playVRStartSound(handler ) {
194
197
195
- if (event is VideoRecordEvent .Start ) {
196
- onRecordingStart()
197
- }
198
+ recording = pendingRecording.start(ctx.mainExecutor) { event ->
198
199
199
- if (event is VideoRecordEvent .Status ) {
200
- updateTimerTime(event.recordingStats.recordedDurationNanos)
201
- }
202
-
203
- if (event is VideoRecordEvent .Finalize ) {
204
- afterRecordingStops()
200
+ if (event is VideoRecordEvent .Start ) {
201
+ onRecordingStart()
202
+ }
205
203
206
- camConfig.mPlayer.playVRStopSound()
204
+ if (event is VideoRecordEvent .Status ) {
205
+ updateTimerTime(event.recordingStats.recordedDurationNanos)
206
+ }
207
207
208
- if (event.hasError()) {
209
- when (event.error) {
210
- VideoRecordEvent .Finalize .ERROR_NO_VALID_DATA -> {
211
- ctx.showMessage(R .string.recording_too_short_to_be_saved)
212
- return @start
213
- }
214
- VideoRecordEvent .Finalize .ERROR_ENCODING_FAILED ,
215
- VideoRecordEvent .Finalize .ERROR_RECORDER_ERROR ,
216
- VideoRecordEvent .Finalize .ERROR_UNKNOWN -> {
217
- ctx.showMessage(ctx.getString(R .string.unable_to_save_video_verbose, event.error))
218
- return @start
219
- }
220
- else -> {
221
- ctx.showMessage(ctx.getString(R .string.error_during_recording, event.error))
208
+ if (event is VideoRecordEvent .Finalize ) {
209
+ afterRecordingStops()
210
+
211
+ camConfig.mPlayer.playVRStopSound()
212
+
213
+ if (event.hasError()) {
214
+ when (event.error) {
215
+ VideoRecordEvent .Finalize .ERROR_NO_VALID_DATA -> {
216
+ ctx.showMessage(R .string.recording_too_short_to_be_saved)
217
+ return @start
218
+ }
219
+ VideoRecordEvent .Finalize .ERROR_ENCODING_FAILED ,
220
+ VideoRecordEvent .Finalize .ERROR_RECORDER_ERROR ,
221
+ VideoRecordEvent .Finalize .ERROR_UNKNOWN -> {
222
+ ctx.showMessage(ctx.getString(R .string.unable_to_save_video_verbose, event.error))
223
+ return @start
224
+ }
225
+ else -> {
226
+ ctx.showMessage(ctx.getString(R .string.error_during_recording, event.error))
227
+ }
222
228
}
223
229
}
224
- }
225
230
226
- val uri = recordingCtx.uri
231
+ val uri = recordingCtx.uri
227
232
228
- if (recordingCtx.isPendingMediaStoreUri) {
229
- try {
230
- removePendingFlagFromUri(ctx.contentResolver, uri)
231
- } catch (e: Exception ) {
232
- ctx.showMessage(R .string.unable_to_save_video)
233
+ if (recordingCtx.isPendingMediaStoreUri) {
234
+ try {
235
+ removePendingFlagFromUri(ctx.contentResolver, uri)
236
+ } catch (e: Exception ) {
237
+ ctx.showMessage(R .string.unable_to_save_video)
238
+ }
233
239
}
234
- }
235
240
236
- if (recordingCtx.shouldAddToGallery) {
237
- val item = CapturedItem (ITEM_TYPE_VIDEO , dateString, uri)
238
- camConfig.updateLastCapturedItem(item)
241
+ if (recordingCtx.shouldAddToGallery) {
242
+ val item = CapturedItem (ITEM_TYPE_VIDEO , dateString, uri)
243
+ camConfig.updateLastCapturedItem(item)
239
244
240
- ctx.updateThumbnail()
245
+ ctx.updateThumbnail()
241
246
242
- if (ctx is SecureMainActivity ) {
243
- ctx.capturedItems.add(item)
247
+ if (ctx is SecureMainActivity ) {
248
+ ctx.capturedItems.add(item)
249
+ }
244
250
}
245
- }
246
251
247
- if (ctx is VideoCaptureActivity ) {
248
- ctx.afterRecording(uri)
252
+ if (ctx is VideoCaptureActivity ) {
253
+ ctx.afterRecording(uri)
254
+ }
249
255
}
250
256
}
251
- }
252
257
253
- try {
254
- // FileDescriptorOutputOptions doc says that the file descriptor should be closed by the
255
- // caller, and that it's safe to do so as soon as pendingRecording.start() returns
256
- recordingCtx.fileDescriptor.close()
257
- } catch (e: Exception ) {
258
- e.printStackTrace()
258
+ try {
259
+ // FileDescriptorOutputOptions doc says that the file descriptor should be closed by the
260
+ // caller, and that it's safe to do so as soon as pendingRecording.start() returns
261
+ recordingCtx.fileDescriptor.close()
262
+ } catch (e: Exception ) {
263
+ e.printStackTrace()
264
+ }
259
265
}
260
266
}
261
267
}
0 commit comments