安卓开发视频抽帧展示出错
想做一个从相册选择视频然后进行抽帧检测处理的app的时候,发现一直闪退,然后就试着只抽取了第一帧的bitmap图像并进行展示,然后就发现仅仅抽取一帧运行时就会直接闪退,想问问各位代码哪里有问题:

安卓开发视频抽帧展示出错
想做一个从相册选择视频然后进行抽帧检测处理的app的时候,发现一直闪退,然后就试着只抽取了第一帧的bitmap图像并进行展示,然后就发现仅仅抽取一帧运行时就会直接闪退,想问问各位代码哪里有问题:

关注引自免费微信小程序:皆我百晓生
在您的代码中,有几个可能的问题导致应用闪退。以下是针对您提供的代码段的修改建议:
首先,确保在尝试访问媒体文件之前已经获取了必要的权限。在AndroidManifest.xml中添加以下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
其次,在Java代码中检查是否已授予存储权限,并请求它们,如果需要的话。您可以使用下面的方法:
// 检查读写权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// 请求权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_WRITE);
} else {
// 已经有权限,可以继续执行代码
}
接着,确保在调用setDataSource()方法时传递正确的数据源类型。对于从相册选择的视频,应该使用ContentResolver来获取正确的URI。
private void processVideo(Uri videoUri) {
ContentResolver contentResolver = getContentResolver();
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(contentResolver, videoUri);
} catch (IOException e) {
Log.e("TAG", "Error setting data source: ", e);
return;
}
...
}
接下来,当处理位图时,确保正确地处理null值,因为getFrameAtTime()可能会返回null,特别是在视频开始时。同时,为了防止内存泄漏,建议使用BitmapFactory.Options对象来优化位图加载。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
retriever.setDataSource(contentResolver, videoUri);
} catch (IOException e) {
Log.e("TAG", "Error setting data source: ", e);
return;
}
int height = retriever.extractHeight(null);
int width = retriever.extractWidth(null);
options.inSampleSize = calculateInSampleSize(options, desiredWidth, desiredHeight);
options.inJustDecodeBounds = false;
Bitmap bitmap1 = null;
try {
bitmap1 = BitmapFactory.decodeStream(retriever.getInputStream(MediaMetadataRetriever.METADATA_KEY_MIME), null, options);
} catch (IOException e) {
Log.e("TAG", "Error decoding bitmap: ", e);
}
if (bitmap1 != null) {
YoLoV5Ncnn.obj[] objs = yolov5ncnn.Detect(bitmap1, use_gpu: true);
Bitmap updatedBitmap = performObjectDetection(objs);
imageView.setImageBitmap(updatedBitmap);
}
这里,calculateInSampleSize()是一个用于计算缩放因子的方法,以减小位图尺寸并降低内存消耗:
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
这些更改应该能解决闪退问题。请将上述代码片段替换到您的项目中,并根据需要调整参数。如果问题仍然存在,请提供具体的错误日志,以便进一步诊断。