Commit e4b07a73 authored by 马乐's avatar 马乐

1.修复截取视频只能截取一次问题

parent 2a27202f
...@@ -8,17 +8,14 @@ import android.media.CamcorderProfile ...@@ -8,17 +8,14 @@ import android.media.CamcorderProfile
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.speech.tts.TextToSpeech import android.speech.tts.TextToSpeech
import android.util.Size
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.arcsoft.visdrive.sdk.ArcErrorInfo import com.arcsoft.visdrive.sdk.ArcErrorInfo
import com.arcsoft.visdrive.sdk.ArcVisDriveEngine import com.arcsoft.visdrive.sdk.ArcVisDriveEngine
import com.arcsoft.visdrive.sdk.constant.common.ArcModType import com.arcsoft.visdrive.sdk.constant.common.ArcModType
import com.arcsoft.visdrive.sdk.model.common.ArcActiveEnvParam import com.arcsoft.visdrive.sdk.model.common.ArcActiveEnvParam
import com.blankj.utilcode.util.JsonUtils
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.TimeUtils import com.blankj.utilcode.util.TimeUtils
import com.intergration.test.databinding.ActivityMainBinding import com.intergration.test.databinding.ActivityMainBinding
...@@ -28,7 +25,13 @@ import com.intergration.test.dms.DmsCoroutineContext ...@@ -28,7 +25,13 @@ import com.intergration.test.dms.DmsCoroutineContext
import com.intergration.test.dms.DmsCoroutineScope import com.intergration.test.dms.DmsCoroutineScope
import com.intergration.test.dms.dmsEngine import com.intergration.test.dms.dmsEngine
import com.intergration.test.dms.initializeDms import com.intergration.test.dms.initializeDms
import com.intergration.test.dms.setDmsAlarmParams import com.intergration.test.dms.setDmsAlarmCallParams
import com.intergration.test.dms.setDmsAlarmCloseEyeParams
import com.intergration.test.dms.setDmsAlarmDistractParams
import com.intergration.test.dms.setDmsAlarmDriverAbnormalParams
import com.intergration.test.dms.setDmsAlarmLensCoveredParams
import com.intergration.test.dms.setDmsAlarmSmokeParams
import com.intergration.test.dms.setDmsAlarmYawnParams
import com.intergration.test.dms.setDmsDistractScope import com.intergration.test.dms.setDmsDistractScope
import com.intergration.test.dms.setDmsDrivingStatus import com.intergration.test.dms.setDmsDrivingStatus
import com.intergration.test.dms.startDms import com.intergration.test.dms.startDms
...@@ -42,10 +45,11 @@ import com.mediatek.smartplatform.SmartPlatformManager ...@@ -42,10 +45,11 @@ import com.mediatek.smartplatform.SmartPlatformManager
import com.mediatek.smartplatform.SpmCameraDevice import com.mediatek.smartplatform.SpmCameraDevice
import com.mediatek.smartplatform.SpmCameraDevice.VideoCallback import com.mediatek.smartplatform.SpmCameraDevice.VideoCallback
import com.mediatek.smartplatform.VideoInfoMap import com.mediatek.smartplatform.VideoInfoMap
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.Locale import java.util.Locale
import java.util.concurrent.CancellationException import java.util.concurrent.CancellationException
...@@ -64,6 +68,8 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba ...@@ -64,6 +68,8 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba
mCamcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P) mCamcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P)
mOutPutFilePath = VIDEO_FOLDER mOutPutFilePath = VIDEO_FOLDER
mVideoCycleDeleteFileNum = 3 mVideoCycleDeleteFileNum = 3
mLockFileNamePrefix = "dms-"
mVideoCallback = this@MainActivity
} }
private var dmsJob:Job? = null private var dmsJob:Job? = null
...@@ -84,6 +90,8 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba ...@@ -84,6 +90,8 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba
TextToSpeech(this,this, TTS_ENGINE) TextToSpeech(this,this, TTS_ENGINE)
} }
private var dmsCameraDevice:SpmCameraDevice? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
...@@ -93,20 +101,17 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba ...@@ -93,20 +101,17 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba
} }
binding.startDms.setOnClickListener { binding.startDms.setOnClickListener {
if (dmsCoroutineScope == null) { if (dmsCoroutineScope == null) {
dmsCoroutineScope = DmsCoroutineScope(DmsCoroutineContext(engine = dmsEngine,SmartPlatformManager.get().openCameraDevice( dmsCameraDevice = SmartPlatformManager.get().openCameraDevice(CAMERA_ID_DMS)
CAMERA_ID_DMS dmsCoroutineScope = DmsCoroutineScope(DmsCoroutineContext(engine = dmsEngine,dmsCameraDevice!!) + Dispatchers.IO + COROUTINE_DMS)
)) + Dispatchers.IO + COROUTINE_DMS
)
} }
LogUtils.d("dms context:${dmsCoroutineScope?.coroutineContext}")
dmsJob = dmsCoroutineScope?.launch { dmsJob = dmsCoroutineScope?.launch {
LogUtils.d("startDms") LogUtils.d("startDms")
try { try {
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.setPreviewSurface(binding.dmsPreview.holder.surface, dmsCameraDevice?.setPreviewSurface(binding.dmsPreview.holder.surface,
PreviewSource.GENERAL_CAMERA) PreviewSource.GENERAL_CAMERA)
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.startPreview() dmsCameraDevice?.startPreview()
recordConfiguration.mLockFileNamePrefix = "dms" dmsCameraDevice?.startRecord(RecordSource.GENERAL_CAMERA,recordConfiguration)
recordConfiguration.mVideoCallback = this@MainActivity
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.startRecord(RecordSource.GENERAL_CAMERA,recordConfiguration)
var result = ArcVisDriveEngine.activate(APP_ID, APP_SECRET, arrayOf(ArcModType.TYPE_DMS,ArcModType.TYPE_FR), var result = ArcVisDriveEngine.activate(APP_ID, APP_SECRET, arrayOf(ArcModType.TYPE_DMS,ArcModType.TYPE_FR),
ArcActiveEnvParam().apply { ArcActiveEnvParam().apply {
this.IMEI = DEVICE_IMEI this.IMEI = DEVICE_IMEI
...@@ -123,24 +128,34 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba ...@@ -123,24 +128,34 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba
LogUtils.d("DMS初始化成功") LogUtils.d("DMS初始化成功")
} else { } else {
LogUtils.e("DMS初始化失败") LogUtils.e("DMS初始化失败")
return@launch
} }
coroutineContext[DmsCoroutineContext]?.engine?.let {engine-> coroutineContext[DmsCoroutineContext]?.engine?.let {engine->
engine.setDmsAlarmParams() engine.setDmsAlarmCallParams()
engine.setDmsDistractScope() engine.setDmsAlarmSmokeParams()
engine.setDmsAlarmCloseEyeParams()
engine.setDmsAlarmYawnParams()
engine.setDmsAlarmDistractParams()
engine.setDmsAlarmDriverAbnormalParams()
engine.setDmsAlarmLensCoveredParams()
engine.setDmsDrivingStatus() engine.setDmsDrivingStatus()
engine.setDmsDistractScope()
} }
coroutineContext[DmsCoroutineContext]?.engine?.let {engine-> coroutineContext[DmsCoroutineContext]?.engine?.let {engine->
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.startDms(engine)?.collect{result-> dmsCameraDevice?.startDms(engine)?.collect{result->
ensureActive()
binding.detectResult.text = result binding.detectResult.text = result
tts.speak(result, TextToSpeech.QUEUE_ADD, null,null) tts.speak(result, TextToSpeech.QUEUE_ADD, null,null)
launch(Dispatchers.IO){ launch(Dispatchers.IO){
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.lockRecordingVideo( ensureActive()
dmsCameraDevice?.lockRecordingVideo(
DOT_PREFACE_DURATION,"",RecordSource.GENERAL_CAMERA) DOT_PREFACE_DURATION,"",RecordSource.GENERAL_CAMERA)
} }
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
repeat(3){ repeat(3){
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.takePicture( ensureActive()
"${Environment.getExternalStorageDirectory().path}/waytous/alarm/dms-${TimeUtils.millis2String(System.currentTimeMillis(),"yyyyMMddHHmmss")}.jpg", dmsCameraDevice?.takePicture(
"${Environment.getExternalStorageDirectory().path}/waytous/alarm/dms-${TimeUtils.millis2String(System.currentTimeMillis(),"yyyyMMdd-HHmmss")}.jpg",
{ }, { i, s, s2 -> } { }, { i, s, s2 -> }
) )
delay(1000) delay(1000)
...@@ -150,9 +165,9 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba ...@@ -150,9 +165,9 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba
} }
} catch (e: CancellationException) { } catch (e: CancellationException) {
LogUtils.e("${e.message}") LogUtils.e("${e.message}")
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.stopPreview() dmsCameraDevice?.stopPreview()
coroutineContext[DmsCoroutineContext]?.spmCameraDevice?.stopRecord(RecordSource.GENERAL_CAMERA) dmsCameraDevice?.stopRecord(RecordSource.GENERAL_CAMERA)
smartPlatformManager.closeCameraDevice(coroutineContext[DmsCoroutineContext]?.spmCameraDevice) dmsCameraDevice?.let { smartPlatformManager.closeCameraDevice(it)}
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
...@@ -170,22 +185,23 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba ...@@ -170,22 +185,23 @@ class MainActivity : AppCompatActivity(),TextToSpeech.OnInitListener,VideoCallba
} }
override fun onVideoTaken(videoInfo: VideoInfoMap?) { override fun onVideoTaken(videoInfo: VideoInfoMap?) {
when(videoInfo?.getInt(VideoInfoMap.KEY_RECORDER_EVENT_TYPE)){ CoroutineScope(Dispatchers.IO).launch {
VideoCallback.VIDEO_EVENT_SDCARD_FULL-> { when(videoInfo?.getInt(VideoInfoMap.KEY_RECORDER_EVENT_TYPE)){
LogUtils.e("SDCard已满") VideoCallback.VIDEO_EVENT_SDCARD_FULL-> {
smartPlatformManager.openCameraDevice(CAMERA_ID_DMS).stopRecord(RecordSource.GENERAL_CAMERA) LogUtils.e("SDCard已满")
} }
VideoCallback.VIDEO_EVENT_RECORD_SDCARD_DAMAGED-> { VideoCallback.VIDEO_EVENT_RECORD_SDCARD_DAMAGED-> {
LogUtils.e("SDCard损坏") LogUtils.e("SDCard损坏")
smartPlatformManager.openCameraDevice(CAMERA_ID_DMS).stopRecord(RecordSource.GENERAL_CAMERA) }
} VideoCallback.VIDEO_EVENT_RECORD_RECORDING_ERROR-> {
VideoCallback.VIDEO_EVENT_RECORD_RECORDING_ERROR-> { LogUtils.e("录制视频过程中发生错误")
LogUtils.e("录制视频过程中发生错误") }
smartPlatformManager.openCameraDevice(CAMERA_ID_DMS).stopRecord(RecordSource.GENERAL_CAMERA) VideoCallback.VIDEO_EVENT_KEYPOINT_STOP ->{
} LogUtils.d("录制打点视频结束")
VideoCallback.VIDEO_EVENT_KEYPOINT_STOP ->{ }
LogUtils.d("录制打点视频结束")
} }
dmsCameraDevice?.stopRecord(RecordSource.GENERAL_CAMERA)
dmsCameraDevice?.startRecord(RecordSource.GENERAL_CAMERA,recordConfiguration)
} }
} }
......
...@@ -73,7 +73,8 @@ fun ArcVisDriveEngine.initializeDms():Int{ ...@@ -73,7 +73,8 @@ fun ArcVisDriveEngine.initializeDms():Int{
ArcDMSDetectMaskType.MOD_DMS_CLOSE_EYE or ArcDMSDetectMaskType.MOD_DMS_CLOSE_EYE or
ArcDMSDetectMaskType.MOD_DMS_YAWN or ArcDMSDetectMaskType.MOD_DMS_YAWN or
ArcDMSDetectMaskType.MOD_DMS_DISTRACT or ArcDMSDetectMaskType.MOD_DMS_DISTRACT or
ArcDMSDetectMaskType.MOD_DMS_DRIVER_ABNORMAL ArcDMSDetectMaskType.MOD_DMS_DRIVER_ABNORMAL or
ArcDMSDetectMaskType.MOD_DMS_LENS_COVERED
} }
val initParamDetail = ArcInitParamInfoDetail() val initParamDetail = ArcInitParamInfoDetail()
initParamDetail.modType = ArcModType.TYPE_DMS initParamDetail.modType = ArcModType.TYPE_DMS
...@@ -83,20 +84,106 @@ fun ArcVisDriveEngine.initializeDms():Int{ ...@@ -83,20 +84,106 @@ fun ArcVisDriveEngine.initializeDms():Int{
return init(arcInfoParam) return init(arcInfoParam)
} }
fun ArcVisDriveEngine.setDmsAlarmParams(interval:Int = 4,speedThreshold:Int = 33){ /**
* 打电话参数设置
*
* */
fun ArcVisDriveEngine.setDmsAlarmCallParams(interval:Int = 30, speedThreshold:Int = 33){
val dmsAlarmParam = ArcDMSAlarmParam() val dmsAlarmParam = ArcDMSAlarmParam()
val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CALL, dmsAlarmParam) val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CALL, dmsAlarmParam)
if (result == ArcErrorInfo.ARC_ERROR_OK) { if (result == ArcErrorInfo.ARC_ERROR_OK) {
dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
/**
* 以下设置参数仅供测试使用,实际使用请根据真实环境设置
*/
dmsAlarmParam.arcAlarmParam.interval = interval dmsAlarmParam.arcAlarmParam.interval = interval
dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CALL, dmsAlarmParam)
}
}
/**
* 抽烟参数设置
*
* */
fun ArcVisDriveEngine.setDmsAlarmSmokeParams(interval:Int = 30, speedThreshold:Int = 33){
val dmsAlarmParam = ArcDMSAlarmParam()
val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_SMOKE, dmsAlarmParam)
if (result == ArcErrorInfo.ARC_ERROR_OK) {
dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
dmsAlarmParam.arcAlarmParam.interval = interval
dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_SMOKE, dmsAlarmParam)
}
}
/**
* 闭眼睛参数设置
*
* */
fun ArcVisDriveEngine.setDmsAlarmCloseEyeParams(interval:Int = 30, speedThreshold:Int = 33){
val dmsAlarmParam = ArcDMSAlarmParam()
val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CLOSE_EYE, dmsAlarmParam)
if (result == ArcErrorInfo.ARC_ERROR_OK) {
dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
dmsAlarmParam.arcAlarmParam.interval = interval
dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_CLOSE_EYE, dmsAlarmParam)
}
}
/**
* 打哈欠参数设置
*
* */
fun ArcVisDriveEngine.setDmsAlarmYawnParams(interval:Int = 30, speedThreshold:Int = 33){
val dmsAlarmParam = ArcDMSAlarmParam()
val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_YAWN, dmsAlarmParam)
if (result == ArcErrorInfo.ARC_ERROR_OK) {
dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
dmsAlarmParam.arcAlarmParam.interval = interval
dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_YAWN, dmsAlarmParam)
}
}
/**
* 分神参数设置
*
* */
fun ArcVisDriveEngine.setDmsAlarmDistractParams(interval:Int = 30, speedThreshold:Int = 33){
val dmsAlarmParam = ArcDMSAlarmParam()
val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DISTRACT, dmsAlarmParam)
if (result == ArcErrorInfo.ARC_ERROR_OK) {
dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_MEDIUM
dmsAlarmParam.arcAlarmParam.interval = interval
dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DISTRACT, dmsAlarmParam)
}
}
/**
* 驾驶员异常参数设置
*
* */
fun ArcVisDriveEngine.setDmsAlarmDriverAbnormalParams(interval:Int = 120, speedThreshold:Int = 33){
val dmsAlarmParam = ArcDMSAlarmParam()
val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DRIVER_ABNORMAL, dmsAlarmParam)
if (result == ArcErrorInfo.ARC_ERROR_OK) {
dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_LOW
dmsAlarmParam.arcAlarmParam.interval = interval
dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_DRIVER_ABNORMAL, dmsAlarmParam)
}
}
/**
* 遮挡镜头参数设置
*
* */
fun ArcVisDriveEngine.setDmsAlarmLensCoveredParams(interval:Int = 60, speedThreshold:Int = 33){
val dmsAlarmParam = ArcDMSAlarmParam()
val result = getDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_LENS_COVERED, dmsAlarmParam)
if (result == ArcErrorInfo.ARC_ERROR_OK) {
dmsAlarmParam.sensitivityLevel = ArcAlarmSensitivityLevel.ALARM_SENSITIVITY_LOW
dmsAlarmParam.arcAlarmParam.interval = interval
dmsAlarmParam.arcAlarmParam.speedThreshold = speedThreshold
setDMSAlarmParam(ArcDMSAlarmType.ALARM_DMS_LENS_COVERED, dmsAlarmParam)
} }
} }
fun ArcVisDriveEngine.setDmsDistractScope(leftYaw:Int = -20,rightYaw:Int = 20,upPitch:Int = 20,downPitch:Int = -20):Int{ fun ArcVisDriveEngine.setDmsDistractScope(leftYaw:Int = -30,rightYaw:Int = 30,upPitch:Int = 20,downPitch:Int = -20):Int{
val dmsScope = ArcDMSDistractScope() val dmsScope = ArcDMSDistractScope()
var result = getDMSDistractScopeParam(dmsScope) var result = getDMSDistractScopeParam(dmsScope)
return if (result == ArcErrorInfo.ARC_ERROR_OK) { return if (result == ArcErrorInfo.ARC_ERROR_OK) {
...@@ -182,7 +269,7 @@ fun SpmCameraDevice.startDms(engin:ArcVisDriveEngine) = callbackFlow{ ...@@ -182,7 +269,7 @@ fun SpmCameraDevice.startDms(engin:ArcVisDriveEngine) = callbackFlow{
} }
startPictureSequence(PictureSequenceSource.GENERAL_CAMERA,pictureConfig) startPictureSequence(PictureSequenceSource.GENERAL_CAMERA,pictureConfig)
awaitClose { awaitClose {
LogUtils.dTag("dms","dms detect ended") LogUtils.e("dms","dms detect ended")
stopPictureSequence(PictureSequenceSource.GENERAL_CAMERA) stopPictureSequence(PictureSequenceSource.GENERAL_CAMERA)
engin.unInit() engin.unInit()
} }
......
...@@ -16,7 +16,6 @@ const val TTS_ENGINE = "com.iflytek.speechcloud" ...@@ -16,7 +16,6 @@ const val TTS_ENGINE = "com.iflytek.speechcloud"
const val VIDEO_FOLDER = "sdcard/waytous/alarm/" const val VIDEO_FOLDER = "sdcard/waytous/alarm/"
fun SpmCameraDevice.recordVideo(prefix:String){ fun SpmCameraDevice.recordVideo(prefix:String){
val recordConfiguration = RecordConfiguration.get(RecordSource.GENERAL_CAMERA).apply { val recordConfiguration = RecordConfiguration.get(RecordSource.GENERAL_CAMERA).apply {
mLockFileNamePrefix = prefix mLockFileNamePrefix = prefix
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment