SurfaceTexture 的 onFrameAvailable() 方法总是调用得太晚

2023-11-29

我正在尝试让以下 MediaExtractor 示例正常工作:

http://bigflake.com/mediacodec/ - ExtractMpegFramesTest.java(需要 4.1,API 16)

我遇到的问题是 outputSurface.awaitNewImage();似乎总是抛出 RuntimeException("frame wait timed out"),每当mFrameSyncObject.wait(TIMEOUT_MS)呼叫超时。不管我设置什么TIMEOUT_MS to be, onFrameAvailable()总是被打电话就在之后发生超时。我尝试了 50ms 和 30000ms,结果是一样的。

似乎是onFrameAvailable()线程繁忙时无法调用,一旦超时结束线程代码执行,它可以解析onFrameAvailable() call.

有没有人设法让这个例子工作,或者知道 MediaExtractor 应该如何与 GL 纹理一起工作?

Edit:在具有 API 4.4 和 4.1.1 的设备上尝试过此操作,并且在两者上都会发生同样的情况。

Edit 2:

感谢 fadden,让它在 4.4 上运行。问题是ExtractMpegFramesWrapper.runTest()方法称为th.join();这阻塞了主线程并阻止了onFrameAvailable()正在处理呼叫。有一次我评论了th.join();它适用于 4.4。我想也许是ExtractMpegFramesWrapper.runTest()它本身应该在另一个线程上运行,这样主线程就不会被阻塞。

4.1.2 调用时也出现了一个小问题codec.configure(),它给出了错误:

A/ACodec(2566): frameworks/av/media/libstagefright/ACodec.cpp:1041 CHECK(def.nBufferSize >= size) failed.
A/libc(2566): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 2625 (CodecLooper)

我通过在调用之前添加以下内容解决了这个问题:

format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 0);

然而,我现在在 4.1.1 (Galaxy S2 GT-I9100) 和 4.1.2 (Samsung Galaxy Tab GT-P3110) 上遇到的问题是,它们总是将所有帧的 info.size 设置为 0。这是日志输出:

loop
input buffer not available
no output from decoder available
loop
input buffer not available
no output from decoder available
loop
input buffer not available
no output from decoder available
loop
input buffer not available
no output from decoder available
loop
submitted frame 0 to dec, size=20562
no output from decoder available
loop
submitted frame 1 to dec, size=7193
no output from decoder available
loop
[... skipped 18 lines ...]
submitted frame 8 to dec, size=6531
no output from decoder available
loop
submitted frame 9 to dec, size=5639
decoder output format changed: {height=240, what=1869968451, color-format=19, slice-height=240, crop-left=0, width=320, crop-bottom=239, crop-top=0, mime=video/raw, stride=320, crop-right=319}
loop
submitted frame 10 to dec, size=6272
surface decoder given buffer 0 (size=0)
loop
[... skipped 1211 lines ...]
submitted frame 409 to dec, size=456
surface decoder given buffer 1 (size=0)
loop
sent input EOS
surface decoder given buffer 0 (size=0)
loop
surface decoder given buffer 1 (size=0)
loop
surface decoder given buffer 0 (size=0)
loop
surface decoder given buffer 1 (size=0)
loop
[... skipped 27 lines all with size=0 ...]
surface decoder given buffer 1 (size=0)
loop
surface decoder given buffer 0 (size=0)
output EOS
Saving 0 frames took ? us per frame // edited to avoid division-by-zero error

所以没有保存任何图像。然而,相同的代码和视频适用于 4.3。我使用的视频是一个 .mp4 文件,带有“H264 - MPEG-4 AVC (avc1)”视频编解码器和“MPEG AAC Audio (mp4a)”音频编解码器。

我也尝试过其他视频格式,但它们似乎在 4.1.x 上消失得更快,而两者都可以在 4.3 上工作。

Edit 3:

我按照你的建议做了,似乎正确保存了帧图像。谢谢。

关于KEY_MAX_INPUT_SIZE,我尝试不设置,或者将其设置为0,20,200,...200000000,所有结果都与info.size=0相同。

我现在无法将渲染设置为布局上的 SurfaceView 或 TextureView。我尝试替换这一行:

mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());

有了这个,哪里surfaceTexture是我的 xml 布局中定义的 SurfaceTexture:

mSurfaceTexture = textureView.getSurfaceTexture();
mSurfaceTexture.attachToGLContext(mTextureRender.getTextureId());

但它引发了一个奇怪的错误getMessage()==null在第二行。我找不到任何其他方法让它在某种视图上绘制。如何更改解码器以在 Surface/SurfaceView/TextureView 上显示帧而不是保存它们?


The way SurfaceTexture工作使这变得有点棘手。

The docs说帧可用回调“在任意线程上调用”。这SurfaceTexture类有一些代码在初始化时执行以下操作(line 318):

if (this thread has a looper) {
    handle events on this thread
} else if (there's a "main" looper) {
    handle events on the main UI thread
} else {
    no events for you
}

框架可用事件通过通常的方式传递到您的应用程序Looper / Handler机制。该机制只是一个消息队列,这意味着线程需要位于Looper事件循环等待他们到达。问题是,如果你睡在awaitNewImage(),你没有看Looper队列。所以事件到来了,但没有人看到它。最终awaitNewImage()超时,线程返回监视事件队列,并立即发现待处理的“新帧”消息。

因此,诀窍是确保帧可用事件到达与所在线程不同的线程。awaitNewImage()。在里面ExtractMpegFramesTest例如,这是通过在新创建的线程中运行测试来完成的(请参阅ExtractMpegFramesWrapper类),它没有Looper。 (由于某种原因,执行 CTS 测试的线程有一个循环程序。)帧可用事件到达主 UI 线程。

更新(针对“编辑 3”):我有点难过,忽略“大小”字段有帮助,但在 4.3 之前,很难预测设备的行为方式。

If you just想要显示框架,通过Surface你从SurfaceView or TextureView进入MediaCodec解码器configure()称呼。那么你就不用再去打扰SurfaceTexture根本没有——帧将在您解码时显示。请参阅以下两个“播放视频”活动:Grafika举些例子。

如果你真的想经历一个SurfaceTexture,您需要更改 CodecOutputSurface 以渲染到窗口表面而不是 pbuffer。 (离屏渲染已经完成,所以我们可以使用glReadPixels()在无头测试中。)

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

SurfaceTexture 的 onFrameAvailable() 方法总是调用得太晚 的相关文章

  • 如何使用 kotlin Android 从 Url 读取 JSON?

    我正在使用 kotlin 来开发应用程序 现在我想从服务器获取 JSON 数据 在java中 我实现了Asyntask以及Rxjava来从Url读取JSON 我也在谷歌搜索 但我无法获得满足我的要求的正确详细信息 如何使用 kotlin 从
  • Realm 中的更新语句

    I have VisitingCardPOJO表格 我想更新单个条目说在哪里no 3 VisitingCardPOJO java public class VisitingCardPOJO extends RealmObject Prima
  • 模仿 youtube/gmail 应用程序的导航抽屉

    背景 近几个月来 谷歌发布了Youtube 应用程序 http www androidpolice com 2013 08 19 breaking massive youtube for android v5 0 update brings
  • 使用 ActiveAndroid 库存储 HashMap

    我有一堂课 Table name Control public class Control extends Model Column private String name Column private Map
  • Android中如何通过ViewModel类在Activity和Fragment之间共享数据?

    我想知道是否可以传递一个在 Activity 类中声明的字符串数据 并将该字符串数据传递给 ViewModel 类 然后将数据传递给 Fragment 类 视图模型类 class TimeTableViewModel extends Vie
  • 如何在android中获取MapView API?

    如何在android中获取MapView API thanks Android 文档中实际上是这么写的 你好 地图视图 http developer android com guide tutorials views hello mapvi
  • 使用 NEON 内在函数除以浮点数

    我当时正在处理四个像素的图像 这是在armv7对于 Android 应用程序 我想分一个float32x4 t向量由另一个向量组成 但其中的数字与大约不同0 7 to 3 85 在我看来 除法的唯一方法是使用右移 但这是针对一个数字2 n
  • Android 从 C++ 端播放原始音频

    我需要能够在 Android 系统的 C 端以自定义文件格式传输音频 我正在致力于移植自定义媒体播放器 并且需要能够打开自定义文件并从中传输音频 这很重要 因为我认为从性能角度来看将整个播放器移植到 JAVA 是不可行的 并且通过 JNI
  • 如何在 M1 Mac 上运行的模拟器上运行旧版 Android 版本(例如 API 级别 21)?

    虽然现在有一个适用于 M1 mac 的 Android Studio 和支持arm架构的Android模拟器镜像 https stackoverflow com questions 64907154 android studio emula
  • 通过意图使用多个电话号码添加新联系人

    我想使用添加新联系人ContactsContract Intents Insert 但问题是我不知道可以有多少个电话号码 据我了解 我只能使用三个电话号码PHONE SECONDARY PHONE TERTIARY PHONE常数 有什么办
  • 多种语言的多种字体

    我最近在开发应用程序时遇到了一种情况 我必须在文本视图中显示不同的语言 目前我正在展示一些使用字体 字体像这样 Typeface tf Typeface createFromAsset this getAssets DroidHindi t
  • Android:文本淡入和淡出

    我已阅读此 stackoverflow 问题和答案 并尝试实现文本淡入和淡出 Android中如何让文字淡入淡出 https stackoverflow com questions 8627211 how to make text fade
  • 如何调试“com.android.okhttp”

    在android kitkat中 URLConnection的实现已经被OkHttp取代 如何调试呢 OkHttp 位于此目录中 external okhttp android main java com squareup okhttp 当
  • 在 Android 中跨单元测试和仪器测试共享资源

    现在谷歌已经添加了实验单元测试支持 http tools android com tech docs unit testing support 如何在单元测试和仪器测试之间共享资源 例如 假设我有一个TestUtils java我希望在单元
  • 表面视图+gl表面视图+框架布局

    我是 java 和 OpenGL 的新手 我正在尝试获得一个相机预览屏幕 能够 同时显示 3D 对象 浏览完样本后 api 演示 我想结合示例的代码 api 演示就足够了 但不知何故它不起作用 迫使我 启动时关闭 错误被称为空指针 例外 有
  • Android Gradle 问题 - Flutter / Dart

    我的 Gradle 同步有问题 我使用 IntelliJ 和 Android Studio 构建 Flutter Dart 应用程序 我添加了 2 个新的依赖项 现在 Gradle 出现了问题 在 Android Studio 中一切正常
  • 如何仅从 Firestore 获取最新更新的数据?

    在 Firestore 上发现任何更改时始终获取整个文档 如何只获取最近更新的数据 这是我的数据 我需要在第一次加载时在聊天中按对象顺序 例如 2018 09 17 30 40 msg和sendby 并且如果数据更新则仅获取新的msg和se
  • Jetpack Compose 中复选框中的透明复选标记

    在我的 Compose 应用程序中 我需要创建一个圆形复选框 我已经通过下面的代码实现了这一点 Composable fun CircleCheckBox isChecked Boolean modifier Modifier Modifi
  • Android SHA1 发布密钥库无法与 Google 地图配合使用

    我正在使用 Google Maps Android API 但遇到了一些问题 我正在使用 android studio 签署我的 apk 在 android keystore jks 创建一个 另外 我选择 发布 作为其中的类型 我已经使用
  • Android TextureView 和硬件加速

    我正在尝试实现上所示的示例这一页 http developer android com reference android view TextureView html 我已经在运行 android 4 及以上版本的三种不同设备上进行了尝试

随机推荐

  • 应用程序脚本 - function () { [本机代码] }

    我正在制作一个谷歌应用程序脚本 我正在尝试制作一个可以读取第一个 callendar 事件的程序 问题是 当我尝试从中获取任何内容时 它只会写 function 本机代码 我看过一些为 javascript 编写的问题 但我不明白如何将 j
  • 如何触摸画布?

    这里是颤振新手 我目前正在尝试使用 Flutter 构建一个简单的触摸绘图应用程序 但无法弄清楚如何触发画布重新绘制 我所拥有的是这样的 我有一个 CustomPaint 小部件 其中包含一个 GestureDetector 子部件 每当发
  • 标准流的输入流/输出流 - Java

    我的理解是 字符流和字节流在C内部工作FILE stream C世界中的标准流是FILE stdin FILE stdout FILE stderr 输入流 and 输出流正在为文件 管道等资源提供子类 输入流 and 输出流api文档不讲
  • C++ 中的返回类型

    include
  • 不使用 intdiv() 的大数整数(64 位)除法(php7 之前)

    测试是在64位系统下进行的 php7有一个很好的功能 intdiv 下面的代码可以完美运行 number 0x7fffffffffffffff result intdiv number 62 结果是148764065110560900 其余
  • Java 8 SSLContext.getInstance("TLSv1.2") 是什么意思?

    我正在尝试为某个端点 URL 调用 REST API 它对于 java net 的 URL 运行良好 并且在执行相同的操作后 但在某些机器上 它因某些 SSLException 而失败 因此代码被修改如下 HttpsURLConnectio
  • Azure 共享访问签名 - 签名不匹配

    我收到此错误
  • 绘制重叠柱形图或条形图

    我需要使用柱形或条形类型将 4 个系列数据绘制到 MSChart 我可以绘制这 4 个系列 以便数据重叠而不是堆叠 我刚刚发现有一个ChartGroup OverlapOffice Excel 的属性 我该如何在 MSChart 中做到这一
  • Java:如何控制JPanel的宽高比?

    我有一个 JPanel 我想保持正方形 但我希望它的大小能够填充其父 JFrame 中可能的最大空间量 但保持正方形 即它采用 JFrame 的最短边作为正方形宽度 我搜索过网络 检查了所有布局管理器 似乎没有一个可以简单地解决这个非常简单
  • 需要更新SQLite中某列的值

    我需要对列中所有行的列值求反 我尝试使用以下查询来执行此操作 但它没有更新任何行 sqliteDatabase rawQuery UPDATE SQL TABLE NAME SET COL 1 COL 1 null 其中COL 1 col
  • 条件 WHERE 语句 SQL Server

    我想创建一个 SP 来返回所有Country行 除非CountryID作为参数提供 这是我想象的它可能的工作方式 但它不喜欢它 ALTER PROCEDURE dbo usp return countries CountryID AS IN
  • HTML5 将加密的视频帧绘制到画布(带有clearkey的加密媒体扩展)

    我正在尝试使用 Javascript 将 HTML5 视频元素中的帧绘制到画布 其中视频 webm VP9 已使用 Clearkey 加密 我正在使用 EME 在 Chrome 中解密它 使用 EME 加密媒体扩展 时 Chrome gt
  • 检测我何时在页面顶部滚动 UIWebView

    我想在我的 webview 顶部添加一个 URL google 栏 并像 Safari 一样通过向上滚动我的网页来访问它 为此 我将检测用户何时滚动页面 以及何时滚动到达顶部 但我实在不知道怎么办 一个主意 非常感谢 Martin 我也在挖
  • 如何在 Perl 中解析 XML 并创建树结构

    我正在解析 XML 文件XML Simple 有没有办法从 XML 中获取树形形式 如果是这样 请举例说明或建议 CPAN 包 我想知道之后我必须处理哪个标签column等等 标签没有顺序 这column标签可以出现在Table or di
  • 用于检索各种日期范围内的 SUM 的 SQL 查询

    我有一个表格 其中包含有关已售产品 客户 购买日期和已售单位摘要的信息 我想要得到的结果应该是 4 行 其中前三行是一月 二月和三月 最后一行是这 3 个月内未售出的产品 这是桌子 http imageshack us a img823 8
  • 不能对承诺式任务调用 Start。异常即将到来

    我正在创建一个简单的 wpf 桌面应用程序 UI 只有一个按钮和 cs 文件中的代码 例如 private void Button Click 2 object sender RoutedEventArgs e FunctionA publ
  • 随机数类内初始化

    我目前正在创建一个类 我希望每次创建对象时都用随机数初始化其中一个私有成员 下面的代码不会产生任何问题 private unsigned random rand 10 不过 我想使用 C 11 随机引擎和发行版来执行此操作 我希望能够按照以
  • 如何在android中的asynctask中检查互联网连接

    Override protected void onCreate Bundle savedInstanceState TODO Auto generated method stub super onCreate savedInstanceS
  • Woocommerce 多个结账页面

    所以我一直在用头撞我的电脑 试图弄清楚如何让它工作 并且想知道这是否可能 只要做一些工作 一切皆有可能 我的最终目标是拥有多个包含 Woocommerce 结帐表单的页面 以便我可以拥有一个用于自定义单页订阅结帐的页面 当我通过设置面板将结
  • SurfaceTexture 的 onFrameAvailable() 方法总是调用得太晚

    我正在尝试让以下 MediaExtractor 示例正常工作 http bigflake com mediacodec ExtractMpegFramesTest java 需要 4 1 API 16 我遇到的问题是 outputSurfa