卧式纯绿 2024-04-16 22:00 采纳率: 26.9%
浏览 2

安卓开发对视频进行抽帧检测出错

安卓开发对从相册获取的视频uri进行抽帧检测出错
存储权限什么的都没有任何问题,主要是抽帧之后的步骤不知道哪里有问题

img


这是处理视频的代码
循环中用一个队列存储渲染后的帧图像,然后在渲染线程中进行展示

img


上面是渲染的步骤就是一个简单的图像展示
下面是线程的操作,取出每一帧图像进行渲染

  • 写回答

4条回答 默认 最新

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

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

    根据您提供的代码,看起来主要的问题在于可能的多线程同步问题以及可能存在的资源泄漏。这里我对您的代码进行了优化,并提供了详细的解释。

    首先,关于多线程同步,您应该使用CountDownLatch来确保主线程等待渲染线程完成后再继续执行。此外,为了防止资源泄漏,您可以使用try-with-resources语句来自动关闭MediaMetadataRetriever对象。另外,为了简化代码,可以将线程的操作封装在一个方法中。

    以下是修改过的代码:

    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    private ExecutorService executorService = Executors.newSingleThreadExecutor();
    private CountDownLatch countDownLatch = new CountDownLatch(1);
    
    private void processVideo(Uri videoUri) {
        try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
            retriever.setDataSource(videoUri.toString());
            
            String timeFormat = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
            Long videoLengthInMills = Long.parseLong(timeFormat) * 1000;
            Long frameInterval = 34000L;
    
            for (Long currentTime = 0; currentTime < videoLengthInMills; currentTime += frameInterval) {
                executorService.submit(() -> {
                    Bitmap bitmap = retriever.getFrameAtTime(currentTime, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                    
                    if (bitmap != null) {
                        YoloV5Ncnn.obj[] objects = yolov5ncnn.Detect(bitmap, use_gpu: true);
                        Bitmap updatedBitmap = performObjectDetection(objects);
                        
                        renderQueue.add(updatedBitmap);
                    }
                });
            }
    
            // 等待所有任务完成
            countDownLatch.await();
            
            // 清理资源
            retriever.release();
            executorService.shutdown();
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    
    private void renderBitmap(Bitmap bitmap) {
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                imageView.setImageBitmap(bitmap);
            }
        });
    
        // 当渲染完成时,减少计数器
        countDownLatch.countDown();
    }
    

    这个版本的代码做了以下改进:

    1. 使用了try-with-resources来自动关闭MediaMetadataRetriever
    2. 使用ExecutorService替代手动创建线程,这样可以更好地管理线程池,提高效率。
    3. 使用CountDownLatch来同步主线程和渲染线程,确保主线程等待所有视频帧处理完成后才继续执行。
    4. 在渲染线程完成后调用countDownLatch.countDown()减少计数器,以便主线程知道渲染已完成。
    5. 删除了不必要的代码块(如renderThread.start()renderThread.interrupt()等)。

    现在,当调用processVideo方法后,主线程会等待所有帧处理完毕再继续执行,同时资源泄漏的风险也得到了降低。如果您还有其他问题或需要进一步的帮助,请随时告诉我。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月16日

悬赏问题

  • ¥15 phython如何实现以下功能?查找同一用户名的消费金额合并—
  • ¥15 ARIMA模型时间序列预测用pathon解决
  • ¥15 孟德尔随机化怎样画共定位分析图
  • ¥18 模拟电路问题解答有偿速度
  • ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
  • ¥15 误删注册表文件致win10无法开启
  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序,怎么查看客户esp32板子上程序及烧录地址
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)