Android MediaCodec 在异步模式下比同步模式下慢?

2024-05-02

再次,我有一个关于 Android 的 MediaCodec 类的问题。

我已成功解码原始 h264 内容并将结果显示在两个纹理视图中。 h264 流来自运行 openGL 场景的服务器。

该场景有一个摄像头,因此可以响应用户输入。

为了进一步减少服务器上的输入与智能手机上的实际结果之间的延迟,我正在考虑在异步模式下使用 MediaCodec。

以下是我设置两种变体的方法:同步和异步:

Async:

//decoderCodec is "video/avc"
MediaFormat fmt = MediaFormat.createVideoFormat(decoderCodec, 1280,720);
codec.setCallback(new MediaCodec.Callback() {

    @Override
    public void onInputBufferAvailable(MediaCodec codec, int index) {
        byte[] frameData;
        try {
            frameData = frameQueue.take(); //this call is blocking
        } catch (InterruptedException e) {
            return;
        }

        ByteBuffer inputData = codec.getInputBuffer(index);
        inputData.clear();
        inputData.put(frameData);

        codec.queueInputBuffer(index, 0, frameData.length, 0, 0);
    }

    @Override
    public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
        codec.releaseOutputBuffer(index, true);
    }

     //The two other methods are left blank at the moment.

});


codec.configure(fmt, surface, null, 0);
codec.start();

Sync:(设置类似于异步,除了codec.setCallback(...)部分。两个变体所在的类都是Runnable.

public void run() {

    while(!Thread.interrupted())
    {
        if(!IS_ASYNC) {
            byte[] frameData;
            try {
                frameData = frameQueue.take(); //this call is blocking
            } catch (InterruptedException e) {
                break;
            }

            int inIndex = codec.dequeueInputBuffer(BUFFER_TIMEOUT);

            if (inIndex >= 0) {
                ByteBuffer input = codec.getInputBuffer(inIndex);
                input.clear();
                input.put(frameData);
                codec.queueInputBuffer(inIndex, 0, frameData.length, 0, 0);
            }

            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            int outIndex = codec.dequeueOutputBuffer(bufferInfo, BUFFER_TIMEOUT);

            if(outIndex >= 0)
                codec.releaseOutputBuffer(outIndex, true);
        }
        else sleep(3000); //Just for testing, if we are in Async, this thread has nothing to do actually...
    }
}

两种方法都有效,但我观察到以同步模式播放的视频更加流畅,延迟也更低。

我想出了使用异步模式的想法,因为frameQueue is a LinkedBlockingDeque我推断,如果同步解码器等待新帧数据到达的时间太长,则解码输出可能已经可用,但由于队列的阻塞性质而不会显示。另一方面,我不想做类似的事情busy wait并始终轮询队列、输入缓冲区和输出缓冲区。

因此,我尝试使用回调的 AsyncMode,但得到的结果甚至比同步模式更糟糕。

我现在要问你们的问题是:

为什么?我是否滥用了异步模式?或者是别的什么?

感谢您的任何反馈!

克里斯托夫

Edit:以下是更新后的代码。我只列出更新的部分。这样 @mstorsjo 正确地指出,罪魁祸首是我在等待更多帧数据onInputBufferAvailable()。更新后的版本向另一个 BlockingQueue 提供可用的缓冲区索引。在另一个线程中,我们正在等待新的帧数据和新的缓冲区索引来对帧数据进行排队以进行解码。

public class DisplayThread implements Runnable {
    private BlockingQueue<Integer> freeInputBuffers;
    //skipped the uninteresting parts.

    private void initCodec(String decoderCodec) {       
        //skipped the uninteresting parts.
        codec.setCallback(new MediaCodec.Callback() {

            @Override
            public void onInputBufferAvailable(MediaCodec codec, int index) {
                freeInputBuffers.add(index);
            }

            //Dont care about the rest of the Callbacks for this demo...
        }
    }   

    @Override
    public void run() {
        while(!Thread.interrupted())
        {

            byte [] frameData;
            int inputIndex;

            try {
                frameData = frameQueue.take();
                //this was, indeed the culprit. We can wait in an additional thread for an buffer index to 
                // become free AND to get new frameData. When waiting in the callback, we will slow down 
                // the decoder.
                inputIndex = freeInputBuffers.take();
            } catch (InterruptedException e) {
                break;
            }

            ByteBuffer inputData = codec.getInputBuffer(inputIndex);
            inputData.clear();
            inputData.put(frameData);
            codec.queueInputBuffer(inputIndex, 0, frameData.length, 0, 0);      
        }

        codec.stop();
        codec.release();
    }
}

如果阻止调用,我不会感到惊讶onInputBufferAvailable是罪魁祸首。感觉两者都有可能onInputBufferAvailable and onOutputBufferAvailable在同一个线程中调用,如果您阻塞一个线程,就会阻止另一个线程运行。

我建议更改它,以便您onInputBufferAvailable只需将缓冲区索引推入某个队列,并向另一个线程发出信号,表明现在有另一个缓冲区可用,然后让第二个线程等待队列中的缓冲区,并在那里阻塞获取输入数据。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android MediaCodec 在异步模式下比同步模式下慢? 的相关文章

  • java.lang.Object的hashCode具体使用的算法是什么

    中使用的算法是什么JVM实施java lang Object的隐含的hashCode 方法 OpenJDK or Oracle JDK答案中首选 它依赖于实现 并且在很大程度上 该算法是entirely取决于实施 只要它是一致的 但是 根据
  • 垂直从上到下线手势检测器

    我用的是 手势工具 注意到对于垂直从上到下的线无法检测 因为我在代码中使用生成的手势文件 如下所示 但无法检测垂直从上到下的线手势检测 import java util ArrayList import android app Activi
  • 如何使用 swagger-codegen-plugin (maven) 生成客户端代码?

    我需要使用 swagger codegen plugin for maven 在 eclipse 中生成服务器存根代码 你能帮忙怎么做吗 以及需要什么配置 在 pom xml 中 我找到了这个答案 您只需要像下面这样更改 pom xml 即
  • 是否有最新的 Facebook Java SDK? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 好像没找到最近更新的 如果没有 是否有一个好的 Java 库来执行与 Facebook 的 API 交
  • phonegap html5 android 同步文件系统 IO

    如何使用 PhoneGaps 文件系统 API 同步读写文件 有可用的同步包装器吗 无法通过提供的 api 同步访问文件 从phonegap的实现方式猜测 我怀疑您是否可以编写一个插件来同步执行此操作
  • 如何使用 MotionLayout 调整 TextView 的大小

    我正在尝试创建一个CollapsingToolbar动画使用MotionLayout 我已经成功地将所有内容设置为动画 使其表现得像CollapsingToolbar具有高度的灵活性 这意味着我可以轻松创建很棒的动画 而无需编写大量代码 我
  • 调整 SwipeRefreshLayout 高度,将 View 置于其底部

    I have SwipeRefreshLayout里面一个RelativeLayout 问题是SwipeRefreshLayout占据了屏幕上的所有位置 我需要放置一个视图after这个观点 看图片 https i stack imgur
  • Android OptionsMenu问题,背景始终透明

    我的选项菜单总是不显示背景 背景是透明的 有谁知道如何摆脱这个 我的失败起源活动是从另一个自定义活动扩展的 我在 eclipse 上有这个项目 选项菜单工作正常 但自从我迁移到 AndroidStudio 后 选项菜单始终是透明的 我尝试更
  • 使用 HTTPServletRequestWrapper 包装请求参数

    我有一个可以验证 授权 REST 调用的过滤器 该过滤器需要访问请求参数 因此我为此编写了一个自定义 HTTPServletRequestWrapper import java util Collections import java ut
  • Jetty Plugin 9启动不喜欢icu4j-2.6.1.jar

    我对 mortbay 的 Maven jetty 插件 6 有相同的配置
  • java swing:向 JTree 项目添加自定义图形按钮

    我想在 JTree 中的项目右侧添加一个带有小图标的附加按钮 这可以做到吗 如果是这样 怎么办 thanks Clamp 你在这方面成功了吗 我想做同样的事情 但很难让 JButton 响应用户 设置渲染器以显示按钮的过程很顺利 但所有鼠标
  • 如何关闭导航抽屉以使用返回主页图标按钮?

    我也将操作栏与搜索栏一起使用 并且我需要像后退按钮一样使用 ActionBar ico 但我也在使用导航抽屉 如何关闭 隐藏 禁用导航抽屉菜单以使用后退按钮 我的 ActionBar 代码 Override public boolean o
  • 如何从一个活动检索 Double 值到另一活动?

    我制作了一个包含 2 个活动的应用程序 其中第一个活动包含一些 EditText 十进制数字 另一个活动也包含一些 EditText 十进制 现在我想将一个 EditText 的值传递给另一个 但作为 双 而不是作为一个字符串 因为该值将用
  • 如果我的应用程序安装在 SD 卡上,私人数据也在那里吗?

    我假设应用程序的私有数据 例如 SharedPreferences 和 SQLite 数据库 位于手机的内部存储而不是 SD 卡上 即使应用程序本身安装在 SD 卡上 我在任何地方都找不到对此的简单明确的确认 有人可以确认一下吗 是的 私有
  • 按“重置应用程序首选项”后,我的应用程序的所有权限都被撤销

    我开发了一个应用程序 支持Android 6 0 当我在 设置 gt 应用程序 gt 重置应用程序首选项 中重置应用程序首选项时 我的应用程序的所有权限都将被撤销 并且应用程序不会重新启动 撤销权限后未能重新启动应用程序可能会导致许多意外崩
  • android 中的 java.net.URL ..新手问题

    我是java新手 正在尝试android开发 以下代码生成 malformedURLException 有人可以帮助我识别异常吗 任何提示都会非常有帮助 package com example helloandroid import and
  • JPA 将 BigDecimal 作为整数保存在数据库中

    我在数据库中有这个字段 ITEMCOST NUMERIC 13 DEFAULT 0 NOT NULL 在JAVA中 Entity中的字段定义如下 Column name ITEMCOST private BigDecimal itemCos
  • Java 中的微分方程

    我正在尝试用java创建一个简单的SIR流行病模型模拟程序 基本上 SIR 由三个微分方程组定义 S t l t S t I t l t S t g t I t R t g t I t S 易感人群 I 感染人群 R 康复人群 l t c
  • Jackson 反序列化相当于 @JsonUnwrapped 吗?

    假设我有以下课程 public class Parent public int age JsonUnwrapped public Name name 生成 JSON age 18 first Joey last Sixpack 我如何将其反
  • @Embeddable 中的 @GenerateValue

    我已将实体的 id 分离到一个单独的 Embeddable 类中 该实体如下 Entity Table name users public class Users EmbeddedId private Users pk id private

随机推荐

  • 无法在 web.config 中为 WCF Web 服务设置服务名称属性

    我编写了一个运行良好的 WCF Web 服务 然后我从另一个应用程序复制了该 Web 服务的内容 并创建了一个新的 WCF 文件 该文件在 web config 中创建了一个新文件 但名称属性显示找不到命名空间 以下是我的 WCF 前几行的
  • 开源协同过滤框架

    我想知道是否存在任何开源框架可以帮助我在我的网站中包含以下类型的功能 1 如果我正在查看特定产品 我想看看我可能感兴趣的其他产品 该信息可以通过计算例如除了我正在查看的产品之外我所在地区的其他人 或我的个人资料的任何其他特征 购买的内容来推
  • 如何观察Firebase存储上传事件

    我有一个将照片上传到 Firebase 存储的 iOS 应用程序 以及一个连接到同一个 Firebase 的 Web 应用程序 有没有办法从网络上观察存储的变化 当上传照片时 只有iOS设备本身可以访问UploadTask 并且我没有看到o
  • HtmlAgilityPack 有属性吗?

    我想做的就是 node Attributes class Value 但如果节点没有class属性 就崩溃了 所以 我必须先检查它是否存在 对吧 我怎么做 Attributes不是一个字典 它是一个包含内部字典的列表 并且没有 HasAtt
  • Visual Studio在其他计算机上远程上传和调试

    有没有办法在另一台计算机上远程上传 运行和调试应用程序 我知道您可以将 Visual Studio 远程调试器附加到远程计算机上运行的应用程序 但我正在寻找一种完全自动化的方法来执行此操作 我正在构建一个家庭自动化系统 如果我能为 Visu
  • QWebView / Qt WebKit 不会打开某些 SSL 页面;不允许重定向?

    在带有 Visual C 2008 SP1 的 Windows 7 上全新安装 Qt SDK 1 1 4 我正在使用 Qt Creator 为什么此代码无法加载某些网页 include
  • 围绕右下角对齐图像

    我正在使用相对布局将一个较小的图像叠加在较大的图像之上 我希望较小图像的右下角与较大图像的 B R 角重合 我在布局 XML 中使用边距参数 指定倾斜测量 但这似乎不适用于所有设备和分辨率 在某些情况下 小图像会从边框移动 4 5 像素 是
  • 如何有效地合并两个 BST?

    如何合并两个二叉搜索树并保持BST的性质 如果我们决定从树中取出每个元素并将其插入到另一个元素中 则此方法的复杂度将为O n1 log n2 where n1是树的节点数 比如T1 我们已经拆分了 并且n2是另一棵树的节点数 比如T2 执行
  • 模拟导入失败

    我该如何制作import pkg失败moduleA py 我可以打补丁pkg如果从中导入某些内容则会失败 否则不会失败 test py import os import moduleA from unittest mock import p
  • 如何处理错误“方法‘First’只能用作最终查询操作”

    我想按关系从数据库中的不同表中检索数据 但出现错误 我不知道如何处理 int customer id int Parse this comboBoxnamecustomer SelectedValue ToString a from c i
  • 将 .cer 格式的证书添加到 .bks 密钥库中

    我需要将 cer 格式的证书添加到 BKS 密钥存储中 SO 上对此进行了描述 如何将 cer 转换为 BKS https stackoverflow com questions 21284466 how to convert cer to
  • SQLPLUS 保存到文件

    我必须为我的数据库类使用 SQLPLUS 我们的第一个作业是简单的保存 我按照说明进行操作 我正在使用 PuTTY 访问 sqlplus 在本练习中使用以下 SQL 命令 并尝试使用 SAVE 和 SPOOL 命令将 SQL 命令和输出保存
  • ActionScript 3.0 中缺少运算符重载

    我在 ActionScript 中最怀念的事情之一是缺少运算符重载 特别是 我通过在我的类中添加 Compare 方法来解决这个问题 但这在很多情况下没有帮助 比如当你想使用内置字典之类的东西时 有没有好的方法来解决这个问题 Nope 但添
  • 如何使用Query备份MySQL数据库?

    我们如何使用 Query 备份 MySQL 数据库 就像我们可以使用以下 Query 备份 MS SQL 一样 Query backup database DATABASENAME to disk PATH 使用 mysqldump php
  • OpenCV 在使用 anaconda 的 Linux 上无法与 python 正常工作。收到 cv2.imshow() 未实现的错误

    这就是我得到的确切错误 我的操作系统是 Ubuntu 16 10 OpenCV 错误 未指定错误 该功能未实现 使用 Windows GTK 2 x 或 Carbon 支持重新构建库 如果您使用的是 Ubuntu 或 Debian 请安装
  • 发送到带有联系表格 asp.net 的电子邮件

    我如何使用 ASP NET 中的联系表单向指定的电子邮件地址发送电子邮件 该网站通过托管公司托管 谢谢 MailMessage mail new MailMessage SmtpClient SmtpServer new SmtpClien
  • 将 SelectByText (部分)与 C# Selenium WebDriver 绑定一起使用似乎不起作用

    我正在使用 C 中的 Selenium WebDriver 扩展通过部分文本值 实际前面有一个空格 从选择列表中选择一个值 我无法使用部分文本匹配来使其工作 我做错了什么还是这是一个错误 可重现的例子 using Microsoft Vis
  • 连接系统 R 中的两个或多个数据帧

    我的问题是如何在 R 系统中连接两个或多个数据帧 例如 我有两个数据框 first x y z 1 3 2 4 2 4 5 7 3 5 6 8 second x y z 1 1 1 1 2 4 5 7 我需要这个 x y z 1 3 2 4
  • 如何解析 Spray-routing 中的 get 请求参数?

    这就是代码部分的样子 get respondWithMediaType MediaTypes application json entity as HttpRequest obj gt complete println obj ok 我可以
  • Android MediaCodec 在异步模式下比同步模式下慢?

    再次 我有一个关于 Android 的 MediaCodec 类的问题 我已成功解码原始 h264 内容并将结果显示在两个纹理视图中 h264 流来自运行 openGL 场景的服务器 该场景有一个摄像头 因此可以响应用户输入 为了进一步减少