在 Android 4.1/4.2 设备中使用 MediaCodec.getOutputFormat() 作为编码器的问题

2024-04-22

我正在尝试使用 MediaCodec 将帧(通过相机或解码器)编码为视频。 当通过 dequeueOutputBuffer() 处理编码器输出时,我期望收到返回索引 = MediaCodec.INFO_OUTPUT_FORMAT_CHANGED,因此我可以调用 getOutputFormat() 来获取编码器输出格式作为当前使用的 ffmpeg 复用器的输入。

我测试了一些Android版本4.1~4.3的pad/phone设备。它们都至少有一个硬件视频AVC编码器并用于测试。在版本 4.3 的设备上,编码器在按预期写入编码数据之前会给出 MediaCodec.INFO_OUTPUT_FORMAT_CHANGED,并且从 getOutputFormat() 返回的输出格式可以被复用器正确使用。在 4.2.2 或更低版本的设备上,编码器永远不会给出 MediaCodec.INFO_OUTPUT_FORMAT_CHANGED,同时它仍然可以输出编码的基本流,但复用器无法知道确切的输出格式。

我想问以下问题:

  1. 编码器的行为(在输出编码数据之前是否给出 MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)是否取决于 Android API 级别或各个设备上的芯片?
  2. 如果编码器在MediaCodec.INFO_OUTPUT_FORMAT_CHANGED出现之前写入数据,有没有办法获取编码数据的输出格式?
  3. 编码器仍然在编码数据之前在设备上输出编解码器配置数据(带有标志 MediaCodec.BUFFER_FLAG_CODEC_CONFIG)。它主要用于配置解码器,但是我可以通过编解码器配置数据导出输出格式吗?

我尝试过这些解决方案来获取输出格式但失败:

  • 在整个编码过程中频繁调用 getOutputFormat()。但是,它们都抛出 IllegalStateException,但没有出现 MediaCodec.INFO_OUTPUT_FORMAT_CHANGED。
  • 使用初始 MediaFormat 在开始时配置编码器,如下例所示:

    m_init_encode_format = MediaFormat.createVideoFormat(m_encode_video_mime, m_frame_width, m_frame_height);
    int encode_bit_rate = 3000000;
    int encode_frame_rate = 15;
    int encode_iframe_interval = 2;
    
    m_init_encode_format.setInteger(MediaFormat.KEY_COLOR_FORMAT, m_encode_color_format);
    m_init_encode_format.setInteger(MediaFormat.KEY_BIT_RATE, encode_bit_rate);
    m_init_encode_format.setInteger(MediaFormat.KEY_FRAME_RATE, encode_frame_rate);
    m_init_encode_format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, encode_iframe_interval);
    
    m_encoder = MediaCodec.createByCodecName(m_video_encoder_codec_info.getName());
    m_encoder.configure(m_init_encode_format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    
    // Assume m_init_encode_format is the output format of the encoder
    

    然而,它失败了,因为编码器的输出格式仍然比初始格式“改变”。

请帮助我实现编码器的行为,以及如果缺少所需的 MediaCodec.INFO_OUTPUT_FORMAT_CHANGED,是否有任何解决方案来查询输出格式。


通过比较输出格式和编解码器配置数据,缺少的字段为 csd-0、csd-1 和值为 1869968451 的“what”字段。 (我不明白“什么”字段。它似乎是一个常量,不是必需的。有人能告诉我它的含义吗?)

如果我将编解码器配置数据解析为 csd-1 字段(最后 8 个字节)和 csd-0 字段(剩余字节),则复用器似乎可以正常工作并输出可在所有测试设备上播放的视频。 (但我想问:这个8字节的假设是否正确,或者有更可靠的方法来解析数据?)

但是,我遇到了另一个问题,如果我再次使用 Android MediaCodec 解码视频,则 dequeueOutputBuffer() 获得的 BufferInfo.presentationTimeUs 值对于大多数解码帧来说都是 0。只有最后几帧的时间是正确的。 MediaExtractor.getSampleTime() 获取的采样时间是正确的,并且与我为编码器/复用器设置的值完全相同,但解码的帧时间不是。此问题仅发生在 4.2.2 或更低版本的设备上。

奇怪的是,帧时间不正确,但视频可以在设备上以正确的速度播放。 (我测试过的大多数 4.2.2 或更低版本的设备只有 1 个视频 AVC 解码器。)我是否需要设置可能影响演示时间的其他字段?


的行为MediaCodec编码器在 Android 4.3 中进行了更改,以适应引入MediaMuxer班级。在 Android 4.3 中,您将始终收到INFO_OUTPUT_FORMAT_CHANGED来自编码器。在以前的版本中,您不会。 (我已经更新了相关常见问题解答条目 http://bigflake.com/mediacodec/#q9.)

无法查询编码器的MediaFormat.

我没有使用过基于 ffmpeg 的复用器,所以我不确定它需要什么信息。如果它正在寻找 csd-0 / csd-1 密钥,您可以从CODEC_CONFIG数据包(我认为你必须解析 SPS / PPS 值并将它们放在单独的键中)。检查内容MediaFormat在 4.3 设备上将显示您缺少哪些字段。

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

在 Android 4.1/4.2 设备中使用 MediaCodec.getOutputFormat() 作为编码器的问题 的相关文章

  • 所有任务完成后继续任务

    在某些类中 我想使用 Task 异步加载 2 个集合并停止 busyindicator 我尝试这样的事情 var uiScheduler TaskScheduler FromCurrentSynchronizationContext Wai
  • 获取带有注释的所有类并将它们添加到 android 中的 hashMap

    我不确定这是否可能 但我基本上希望能够轻松地将新项目添加到列表中 只需添加带有特殊注释的类即可 我能想到的唯一例子就是我目前正在做的事情 用户可以完成很多 挑战 目前我的应用程序中有一个用于 挑战 的包 我希望能够在该包中创建一个新类 给它
  • 如何在onSaveInstanceState中使用变量[重复]

    这个问题在这里已经有答案了 我刚刚开始在 android 上学习编程 并且在使用变量时遇到问题onSaveInstanceState 这是我的代码 int resultCode Override public void onCreate B
  • 如何更改android上的hosts文件[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我已经成功root了我的三星Galaxy Mini android 2 2 1 并认为我可以改变任何东西 就像root通常可以的那样 我想更改 And
  • 允许我的应用程序用户从单个帐户发布推文

    我有一个小应用程序 可以显示我的小国家 比利时的公共交通交通问题 例如 我在应用程序中创建了一个系统 允许用户在火车延误时警告所有人 我想做的是允许我信任的用户从我的帐户发布类似 用户 X 说 123456 号列车晚点 3 分钟 之类的推文
  • Android EditText 验证后更改焦点并在对话框中显示错误

    我有一个带有 3 个 EditText 字段的简单活动 用户 通行证 确认 在 用户 字段中输入内容并且该人在键盘上单击 下一步 后 我在那里有一个 setOnFocusChangeListener 来验证输入 如果验证失败 将打开一个对话
  • 相机 java.lang.RuntimeException:setParameters 失败

    我使用创建了一个自定义相机应用程序this https github com davidgatti dgCam源代码 但在少数设备上 例如高分辨率设备 我得到 RuntimeException setParameters failed 我面
  • 聚合联系人会自动添加吗?

    您一定也在其他地方看到过这段代码 但显然这个异常没有答案 编辑 如果您来这里寻找通过 vcardio 恢复联系人的解决方案 这就是它 我在使用时得到了这个vCardIO http code google com p vcardio Andr
  • 哪个线程运行 ContentProvider?

    如果我从 Activity 调用 ContentProvider ContentProvider 会在哪个线程中运行 例如 如果 Activity 被终止并且查询正在 ContentProvider 中执行 会发生什么情况 假设您的网络查询
  • 服务中的膨胀视图显示视图,但不显示布局内的 ImageView

    我已经成功地在服务中扩展了我的布局 但是它没有显示ImageView在 的里面Inflated Layout我不知道为什么 我设置了一个onClickListener在图像视图上 它工作得很好 当我单击绿色方块时记录并停止服务 唯一的问题是
  • 为什么找不到ImageView类?

    当我转到图形布局时 我在创建第一个 Android 应用程序 pdf Android Application Development for For Dummies 中的静默切换模式 时遇到了麻烦 在 main xml 文件中插入了 Ima
  • 从 Android Intent 打开图库应用

    我正在寻找一种打开方式Android来自意图的画廊应用程序 我不想返回图片 而是只是打开图库以允许用户使用它 就像他们从启动器中选择它一样 View pictures folders 我尝试执行以下操作 Intent intent new
  • 从MySQL php中的特定列获取最大ID和最小ID

    我是新来的php现在尝试从中检索数据MySQL到安卓 这是我的工作细节 table In 检索总小时数函数 我想检索最短 ID 时间 and 最大 ID 超时 from MySQL到安卓通过php最后使用下面的代码来获取总小时数 假设 ID
  • Android EditText:在触摸时选择所有文本,并在用户开始输入时清除。

    我的应用程序中有一个编辑文本 当用户触摸编辑文本时 应选择整个文本 而当他开始输入文本时 应清除文本 一个例子是浏览器地址栏 有什么办法可以做到这一点吗 请帮助我 您可以使用以下方法选择 EditText 中的所有文本 android se
  • 错误:Android-XML:将 放置在使用 wrap_content 大小的父元素中可能会导致微妙的错误;使用match_parent

    我是 Android 初学者 正在构建一个linear layout并在布局 XML 文件中收到如下错误 Error Placing a
  • 导航抽屉图标不显示 android

    MainActivity java public class MainActivity extends FragmentActivity public DrawerLayout mDrawerLayout public ListView m
  • 如何在fragment onCreateView中自定义android标题栏

    我正在尝试通过典型方法更改标题栏的视图 Override public View onCreateView LayoutInflater inflater ViewGroup group Bundle args Window window
  • setShadowLayer Android API 差异

    我为我的应用程序开发了一个自定义视图组件 并且正在努力向圆圈添加阴影 这是我的类扩展 View 的代码 public class ChartView extends View public ChartView Context context
  • 我想分享带有单个标题的多张图片

    我想分享带有单个标题的多张图片 该标题显示在一张图像上而不是所有图像上 但标题会显示在一次共享的每张照片上 这是我的代码 private void pic with data Intent shareIntent new Intent sh
  • 在所有布局方法之后调用哪个 Activity 方法?

    我需要做一些事情Activity调用所有布局方法后 所有Views 已就位并且Activity已准备好显示 哪种方法可以做到这一点 如果你想获得视图的宽度或其他东西 这应该有效 将其添加到您的 Activity 的 onCreate 中 V

随机推荐

  • 复制上个月的值并插入到新行中

    这是我当前表的示例 1 表名称 TotalSales Name Year Month Sales Alfred 2011 1 100 我想要做的是创建一个像这样的表 添加一个新行 上个月的销售额 2 表名称 TotalSales Name
  • PHPstorm PHPunit 代码共同覆盖

    当我在 PHPstorm 中运行测试套件时 所有代码覆盖率都为 0 我知道这不是真的 当我从命令行运行 PHPunit 时 记录的 HTML 输出文档显示我实际上确实有覆盖率并列出所有详细信息 在 PHPstorm 中 我将 PHP 解释器
  • 从 xml 节点获取行号 - java

    我已经解析了一个 XML 文件并获得了一个我感兴趣的节点 现在如何在源 XML 文件中找到该节点出现的行号 编辑 目前我正在使用 SAXParser 来解析我的 XML 不过 我会对使用任何解析器的解决方案感到满意 除了节点之外 我还有节点
  • Solr距离过滤

    我正在尝试使用 Solr 进行距离范围搜索 我知道在5公里范围内进行搜索过滤很容易 q fq geofilt pt 45 15 93 85 sfield store d 5 我所追求的是如果我正在寻找一系列的说法 如何做同样的事情5至10公
  • 如何在 Django 管理中显示 ManyToMany 关系的 raw_id 值?

    我有一个应用程序在ForeignKeyField 和ManyToManyField 上使用raw id 管理员在编辑框右侧显示外键的值 不幸的是 它不适用于ManyToMany 我检查了代码 我认为这是正常行为 但是我想知道是否有人有一个简
  • 如何在不同的扬声器上播放声音?

    我的设备有 2 个外部扬声器 我如何分别测试它们 一种功能仅在左侧播放声音 一种功能仅在右侧播放声音 谷歌搜索没有成功 也许我使用了错误的术语 也许使用 WIN32 API 设置余额 如果您谈论的是立体声扬声器系统设置中的 2 个扬声器 那
  • java spring缓存会破坏反射吗?

    我最近正在使用 spring boot 和集成缓存 在我的测试中 我使用了一点反射 这是一个例子 Service public class MyService private boolean fieldOfMyService false p
  • 获取回形针附件的绝对 URL

    是否可以获取回形针附件的绝对 URI 目前的问题是生产环境部署在子 URI 中 在 Passenger 上 RackBaseURI but
  • 如何从内存中为 CircleAvatar 提供图像

    我正在使用带有 backgroundImage 属性的 CircleAvatar 来加载从内存中获取的图像 但出现错误 如何在 flutter 中设置 CircleAvatar 中的 image memory String url GetI
  • 断点改变程序流程

    我正在尝试分析和逆向我拥有的 Objective C 程序 我通过手动更改一些操作码对可执行文件进行了一些修改 然而 当我测试修改后的软件时 我得到 死亡人数 9 没关系 我想我触碰了不该触碰的东西 我当时就推出了gdb myprogram
  • Istio 允许在 Docker Desktop Kubernetes 上使用第三方 JWT

    我使用的是 docker 桌面附带的预打包 Kubernetes 集群 我在 Windows 计算机上 使用 WSL 2 在 Ubuntu 18 04 VM 上运行 Kubernetes 在我的 Kubernetes 集群上 我运行 ist
  • 如何从 Chrome 扩展中的 bg 页面访问弹出页面 DOM?

    在谷歌浏览器中扩展开发者部分 http code google com chrome extensions overview html 它说 扩展内的 HTML 页面 可以完全访问彼此的 DOM 它们可以调用函数 彼此 弹出窗口的内容 是由
  • 何时调用layoutSubviews?

    我有一个自定义视图没有得到layoutSubview动画期间的消息 我有一个充满屏幕的视图 它在屏幕底部有一个自定义子视图 如果我更改导航栏的高度 它可以在 Interface Builder 中正确调整大小 layoutSubviews在
  • git 在推/拉时加密/解密远程存储库文件

    在传输到远程存储库之前是否可以通过 git Push 自动加密文件 并在 git pull 时自动解码它们 也就是说 如果我有一些与 git 存储库共享访问的远程服务器 并且我不希望我们的项目在未经许可的情况下被盗 也许在推之前和拉之后有一
  • NHibernate - 如何使用参数值记录命名参数化查询?

    我有一个参数化的命名查询 如下所示 Query moveOutQuery session createSQLQuery moveOutQueryStr toString addEntity MyClass class setParamete
  • Git rebase 跳过相同的提交

    根据git 变基文档 https git scm com docs git rebase description 如果上游分支已经包含您所做的更改 例如 因为你邮寄了一个已应用于上游的补丁 那么 提交将被跳过 例如 在 以下历史 其中 A
  • 在 Mac 上启动没有停靠图标的 Qt 托盘进程

    我有一个包含 GUI 服务和托盘的捆绑包 请注意 它们是三个独立的过程 这可能听起来很奇怪 托盘是服务的代表 用户可以打开 GUI 如果没有托盘存在 它会创建一个托盘 所以在我的 GUI 代码中我有如下内容 QProcess startDe
  • 使用 Cypress 进行 Auth0 身份验证

    我正在尝试为 Cypress 创建登录命令 并注意到他们关于如何执行此操作的博客与预期值不匹配Auth0反应SDK https auth0 com docs libraries auth0 react 看来他们使用了自定义的 Express
  • 如何在 Python 中将 3D 数据绘制为 2D 网格颜色图?

    我有 3D 数据作为 numpy 数组的列 也就是说 array 0 0 0 0 等 例如 X Y Z 0 0 0 0 1 10 1 0 20 1 1 30 我想绘制此图 以便每个 X Y 坐标都有一个以坐标为中心的正方形 并使用从 例如
  • 在 Android 4.1/4.2 设备中使用 MediaCodec.getOutputFormat() 作为编码器的问题

    我正在尝试使用 MediaCodec 将帧 通过相机或解码器 编码为视频 当通过 dequeueOutputBuffer 处理编码器输出时 我期望收到返回索引 MediaCodec INFO OUTPUT FORMAT CHANGED 因此