【问题标题】:Adding other video codecs / DVD support to JavaFX 2.2向 JavaFX 2.2 添加其他视频编解码器/DVD 支持
【发布时间】:2011-11-16 14:27:12
【问题描述】:

更新:

由于 JFX 的媒体端已经开源,我自己研究了一下,确实有可能,但需要更改和重建 JFX 源代码(Java 和 C 部分)。描述过程here 对于任何想要尝试的人 - 我在该示例中添加了 MKV 支持,但对于其他插件应该非常相似。

因此,问题的其余部分主要是历史问题,但我将把它留在这里以供参考。

背景

到目前为止,我一直在使用 VLCJ 在我的应用程序中播放视频。它可以工作,但如果可能的话,我想看看我是否可以通过迁移到 JavaFX 来实现对通用编解码器的类似支持水平,并为自己省去很多使用多个 VM 的麻烦,比如 VLCJ 需要可靠地播放多个视频。我不会在这里讨论它,但如果您对细节感兴趣,请参阅我对this 问题的回答。还有跨平台兼容性的问题,它可以在 Mac 和 Linux 上运行,但我还没有弄清楚如何让它在 Mac 上显示(我相信有一些安全措施可以防止一个进程访问另一个进程的本机组件,但这又超出了这个问题的范围。)

归结为这样一个事实:虽然它可以工作,但如果有另一种更简单的解决方案,那么使用多个 VM 并稳定地桥接它们会带来很多维护和麻烦。 VLC 确实对播放几乎任何东西都有相当传奇的支持水平,这就是我到目前为止一直使用它的原因,我很想看看我是否可以在 JavaFX 中获得类似的结果 - 或者至少是否可以提供以跨平台方式执行此操作的方法。

研究

JavaFX 2.0 支持视频 - 太棒了!但目前官方的说法是它支持“包含 VP6 视频和 MP3 音频的 FLV”。有没有办法扩展它以添加对更多编解码器的支持?没有我想支持的硬编解码器,它更像是一个尽可能多的情况,所以我正在寻找一种可扩展的方法来解决上述问题。

我想知道它是否会播放机器上本地安装的编解码器的视频,并且它只是不宣传自己(因为该功能显然取决于机器而不是跨平台。)但没有骰子,我已经尝试了一些常见的格式,它确实拒绝播放它所声明的以外的任何东西。

从 JavaFX 1.3 来看,also supports other platform dependant codecs depending on where it's installed。有没有办法通过 JavaFX 2 获得这种行为?还是完全计划在后续版本中发布?我无法在路线图上找到任何有关它的信息或 Oracle 对此的任何评论。

我通过广泛搜索只能找到here,这意味着它可能是可能的,但似乎没有人知道如何。我也很想知道它是否基于 GStreamer 为什么默认情况下也不包含 GStreamer 支持的所有格式?

在使用 JavaFX 播放 DVD 方面,我完全无所适从,所以我假设这只是暂时的。如果有人确实有任何想法或信息,我会全力以赴。

其他方法

我半信半疑的一种方法可能是将 JMC jar 从旧的 JavaFX 中剔除,如 here 所述,并试图使其与 JavaFX 2 一起工作。我认为没有人对此有任何运气方法或类似的东西?

所有事情都失败了,如果有人有任何信息或链接说明是否/何时支持开箱即用的其他编解码器,那么我也很想听听。或者,如果有人有甲骨文某人的任何联系方式,我也可以问一下,我将不胜感激!一段时间以来,我一直渴望在 Java 中提供体面的视频支持,我想这归结为试图弄清楚 JavaFX 是否是这个问题的答案,或者只是另一个半心半意的尝试,它永远不会比它播放更多目前可以!我希望不是后者,但我还没有看到太多证明是这样的。

【问题讨论】:

标签: java video javafx codec vlcj


【解决方案1】:

相信我,我感受到并知道你的沮丧。我已经思考了一段时间,但我不得不使用不直接的方法来解决我的问题。

有很多方法可以解决这个问题,每种方法都有局限性,但取决于适合你的方法:

  1. 文档说 WebView 可与 HTML5 一起使用,它可以播放平台支持的视频(但遗憾的是不支持 Flash)。如果使用 webview 播放视频适合您,您可以尝试一下。你甚至可以用其他节点在它上面绘制。

  2. 便携式 VLC 播放器!如果您正在开发某种投影仪/导演应用程序并且想要全屏视频,您可以让便携式 VLC 播放器在一个屏幕上全屏播放视频,而在另一个屏幕上进行控制。使用了这个解决方案,它适用于 mac 和 windows。 :) 唯一的问题是您不能在视频上绘制节点,因为它是一个外部应用程序,只会产生您应用程序全屏视频的错觉。

  3. 1234563您的本地浏览器。

【讨论】:

  • 还有一件事=) 4. Mencoder 可用于将任何视频文件转换为on2 VP6。我也将它合并到我的应用程序中,它工作得很好。您可以在您的应用中拥有某种“导入视频”功能。
  • 顺便说一下,这是应用程序:bufflogic.com/…
【解决方案2】:

我现在已经成功地将 MKV 支持编译到 JavaFX 中,这确实需要一些努力,但在本机层上也不需要太多努力。有关它的讨论,请参阅here,有关作为补丁/JIRA 票证提交的结果,请参阅here

我已经编写了一份更全面的关于流程 here 的指南,其他任何想要走这条路的人都可能会感兴趣。

以下是我在认真考虑编译其他媒体支持之前的简短调查,但我将把它留在这里以供参考。

现在 JFX8 已经发布并且是完全开源的,我花了一些时间研究如何做到这一点,以及是否可以在不修补 JFX 源代码的情况下做到这一点。不幸的是,后一点的答案几乎是肯定的,至少在没有可怕的字节码操作黑客的情况下是这样。我可能会在以后更实际地研究这个问题,但我会记录我到目前为止从可用源中得出的结果。

魔法从Media constructor 开始,最终从那里弹出MediaException(如果您尝试播放不受支持的格式,则使用MEDIA_UNSUPPORTED 标志。)从那里创建Locator,其构造函数确保 URL 是受支持的。然后在一个单独的线程中调用 init() 方法,该线程对 URL 字符串执行一些完整性检查,读取文件,然后继续尝试找出格式是什么。

这部分方法的相关代码如下:

if (scheme.equals("file") || scheme.equals("jar")) {
    InputStream stream = getInputStream(uri);
    stream.close();
    isConnected = true;
    contentType = MediaUtils.filenameToContentType(uriString); // We need to provide at least something
}

if (isConnected) {
    // Check whether content may be played.
    // For WAV use file signature, since it can detect audio format
    // and we can fail sooner, then doing it at runtime.
    // This is important for AudioClip.
    if (MediaUtils.CONTENT_TYPE_WAV.equals(contentType)) {
        contentType = getContentTypeFromFileSignature(uri);
        if (!MediaManager.canPlayContentType(contentType)) {
            isMediaSupported = false;
        }
    } else {
        if (contentType == null || !MediaManager.canPlayContentType(contentType)) {
            // Try content based on file name.
            contentType = MediaUtils.filenameToContentType(uriString);

            if (Locator.DEFAULT_CONTENT_TYPE.equals(contentType)) {
                // Try content based on file signature.
                contentType = getContentTypeFromFileSignature(uri);
            }

            if (!MediaManager.canPlayContentType(contentType)) {
                isMediaSupported = false;
            }
        }
    }

    // Break as connection has been made and media type checked.
    break;
}

从这里我们可以看到第一次“愚蠢”尝试根据文件名称获取文件内容(这就是MediaUtils.filenameToContentType() 所做的。)然后有一些特殊情况可以检查不同类型的 wav 文件,但是如果失败了,那么我们将依靠更聪明的检查来查看实际的文件签名。这两项检查都在MediaUtils 中。后一种检查范围更广,它会查看文件的前几个字节,看看它是否能以这种方式计算出格式。如果它不能,那么它会退出并抛出异常,然后作为我们可怕的MEDIA_UNSUPPORTED 标志弹出。

如果类型被正确识别,还有另一个障碍需要克服 - 它必须得到当前平台的支持。一些平台会根据环境动态加载,但是GSTPlatform 始终存在,因此我们需要在此处放置任何其他(通用)格式。这比较简单,存在一个CONTENT_TYPES 数组,它只保存支持格式的数组。

不幸的是,目前克隆 JavaFX 存储库对我来说似乎失败了,否则我会尝试将其中的一些内容付诸实践。但代替上述内容,添加对更多格式的支持实际上需要发生什么?实际上看起来并不难。

  1. MediaUtils 中,需要向filenameToContentType() 方法添加支持来处理新的文件扩展名。这是微不足道的。

  2. 在同一个类中,需要向fileSignatureToContentType()方法添加支持,以根据其签名计算文件类型。这有点复杂,但还不算太糟糕。这甚至可能是可选的,因为如果从文件扩展名中没有正确(或根本)识别格式,当前代码似乎只使用它作为后备。可以在 here 找到不同格式的文件签名的完整列表,这应该有助于完成这项任务。

  3. 在 GSTPlatform 中,new content type 需要添加到支持的内容类型列表中。

在 Java 方面,这似乎是让它接受内容类型并至少尝试将其传递给本机 Gstreamer layer 所必需的一切。

但是,我不是 GStreamer 方面的专家,所以虽然我知道它可以处理和播放 JavaFX 目前拒绝的更多格式,但我不确定它们究竟是如何 '已删除此容量。他们肯定已经在上面的 Java 层中做到了,但他们可能也在本机 GStreamer 级别上做到了——在这一点上我不确定。

我认为他们已经对 JFX8 的 GStreamer 进行了一些更改 - 但目前它们并未在 relevant project page 上列出,因此很难准确确定他们为此版本所做的更改。

下一步是获取 JFX8 源,使用上述建议的更改构建新内容类型,然后查看在本机级别发生的错误(如果有),然后从那里获取。

【讨论】:

【解决方案3】:

现在,Javafx2.1 终于支持 mp4 H.264,所以您现在应该可以不用上面发布的特技了。 :)

【讨论】:

  • 但它是否支持 .mkvs? x264 编码,AVC (H.264) 作为视频流,AC-3/DTS 作为音频,即?
  • 我不这么认为。视频只需 on2 flv 和普通 h264,音频流只需 mp3。
  • 这是一个改进,但距离支持大多数常用格式还有很长的路要走,而这正是我想要的!
  • 你和我。但是,在 Oracle 对此采取措施之前,您现在必须依靠变通方法,尽管我认为他们可能很快就会使整个 JFX 堆栈开源,因此可能留给社区来解决。如果视频无法打开,您现在可以合并一个嵌入式 ffmpeg,以便在加载视频之前在您的应用中进行自动转换。
【解决方案4】:

API 设计似乎不支持滚动您自己的编解码器。几乎所有的类都是最终的(例如 VideoTrack、Media、MediaPlayer 等)。我假设目前实际的视频解码是通过内部类完成的,这意味着没有办法覆盖它们。

有一个plan to Open Source JavaFX 2.0,我怀疑我们即将发布 JDK8。希望当他们这样做时,我们可以看到他们如何从 Media(String source) 构造函数中解析他们的编解码器,看看我们是否可以通过某种方式挂钩。

【讨论】:

    【解决方案5】:

    JavaFX 错误跟踪系统中对此的当前开放功能请求:

    阅读链接的功能请求及其相关的 cmets,以了解您正在使用的 JavaFX 分发版本的当前状态(或缺乏状态;-)。

    请注意,对于基于 InputStream 的媒体 API,JavaFX 开发人员后来提出的一个问题是“我建议我们为 JDK 10 考虑这个”,所以我猜将来可能会有这种可能性......

    另外请注意,如果您不确定 JavaFX 当前是否具有对给定编码类型的内置支持,javadoc for the javafx.media package 中提供了支持的媒体编码和媒体容器类型的全面概述(只需确保您查看与您的 JavaFX 版本相匹配的 javadoc 版本)。

    那些可能对其他解决方案感兴趣的人至少可以从 JavaFX 播放视频,即使它是 JavaFX 本身不支持的媒体类型,并且您不想破解原生 JavaFX 媒体支持只是为了获得您的视频播放,也可以看到我对相关问题的回答:

    【讨论】:

    • 谢谢!对我来说,这仍然是一个持续感兴趣的领域——尽管在我发布这个问题之后的 7 年左右时间里,它看起来真的几乎没有什么变化。 InputStream 支持将是一个加号,尽管它不会改变游戏规则,因为它并没有真正改变你可以玩的东西,只是让从某些来源的游戏更有效。我从来没有真正找到一个仅限 JFX 的解决方案;我仍在使用 VLCJ 渲染到画布上 - 但显然这不是满足每个人需求的解决方案!
    猜你喜欢
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多