卧式纯绿 2024-04-19 16:45 采纳率: 26.9%
浏览 1

安卓开发视频抽帧出现问题

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

img

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-19 16:45
    关注

    引自免费微信小程序:皆我百晓生

    在您的代码中,有几个可能的问题导致应用闪退。以下是针对您提供的代码段的修改建议:

    首先,确保在尝试访问媒体文件之前已经获取了必要的权限。在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;
    }
    

    这些更改应该能解决闪退问题。请将上述代码片段替换到您的项目中,并根据需要调整参数。如果问题仍然存在,请提供具体的错误日志,以便进一步诊断。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月19日

悬赏问题

  • ¥15 Matlab在app上输入带有矩阵形式的初始条件发生错误
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址
  • ¥15 elmos524.33 eeprom的读写问题
  • ¥15 用ADS设计一款的射频功率放大器