【问题标题】:How to play raw NAL units in Android exoplayer?如何在 Android exoplayer 中播放原始 NAL 单元?
【发布时间】:2018-05-07 15:45:55
【问题描述】:

我知道 exoplayer 支持 RTSP,但我需要 C++ 代码可以在许多操作系统的播放器上运行,所以我需要在传递给 exoplayer 之前将 C++ 中的 RTP 数据包解析为 NAL 单元

我找到了decode RTP packets using live555 并提取其 NAL 单元的方法。根据ExoPlayer's documentation

所有 ExoPlayer 实现共有的组件是:

定义要播放的媒体、加载媒体以及可以从中读取已加载媒体的 MediaSource。

MediaSource 是 在播放开始时通过 ExoPlayer.prepare 注入。 ...

所以我需要一个自定义的MediaSource,它可以从我的 C++ 代码中提取 NAL 单元。

class reference for MediaSource,我们可以看到已经有一些MediaSources 可用。我虽然也许 SmoothStreaming MediaSource 可以工作,但没有描述它究竟做了什么,在它的构造函数中我必须提供一个 Uri 或一个 SsManifest (什么)。

我可以看到这个库中有一个NAL unit utility,所以也许事情已经完成了一半

那么如何构建或使用已经可用的 MediaSource 来读取 NAL 单元以供 ExoPlayer 播放?

作为补充,您如何将 NAL 单元从 C++ 传递到 Java?在代码中,我发现它只是将它们存储在 C++ 缓冲区中。我应该以某种方式在 Java 中读取这个缓冲区吗?

更新:

我一直在研究这个库的工作原理。这一切都始于MediaSource,其中包含ExtractorDataSource 之类的对象。似乎ExtractorMediaSourceMediaSource,您可以在其中提供自己的ExtractorDataSource

据我了解,DataSource 是一个从任何可能的地方获取原始字节的类,无论是文件读取还是网络数据包。基于库中可用的Extractor 类,如Mp4ExtractorMp3ExtractorExtractor 可以解释从DataSource 读取的数据。 Extractor 接口的两个主要方法是:

void init(ExtractorOutput output)
int read(ExtractorInput input, PositionHolder seekPosition)

我不知道ExtractorInputExtractorInput 是干什么用的,但它们看起来很重要。

所以Extractor 不知何故从DataSource 读取,解析它并以通用格式发送到Renderer

我需要知道这种通用格式是怎样的,这样我才能解析从自定义 DataSource 读取的 NAL 单元。

【问题讨论】:

    标签: java android c++ video h.264


    【解决方案1】:

    您无法使用 ExoPlayer 播放 NAL 单元或原始 H.264 流。
    图片数据必须存在于supported container/format中。

    不清楚你神秘的 C++ 代码在做什么,是 NDK 设置吗?它在Android解码中的作用是什么?您是说您无法将 [来自 C++ 函数] 一个数据数组作为函数参数传递给某个 Android 函数吗?是这样的Java to C++ setup吗?目前还不清楚你真正的问题是什么......

    如果你坚持使用 Exoplayer,我可以告诉你 FLV 是一个(在容器列表中)可能是最好的选择,因为它可以实时构建(重新混合)。您首先创建一个包含 SPSPPS 数据的 FLV 标头,然后是关键帧(从第一个 NAL 中提取的 H264 数据)。您必须熟悉 FLV 字节结构,但每个帧头大约为 13 个字节,后跟 NAL 数据,每帧重复直到结束。这将是实时转码。

    作为第二个选项,对于 Android,您可以只使用 MediaCodec 来解码从 NAL 单元中提取的 H264。这是useful example source。只需用作:

    MediaCodec.createDecoderByType("video/avc"); //then later give NAL units
    

    还可以研究另一个 source 的功能,了解它如何通过 Android 自己的解码器工作。

    其他起点:

    【讨论】:

    • 我正在编写一个 RTP 接收器,它必须在 Android、iOS 和 Windows 上运行,所以它是用 C++ 编写的。我想将作为最终单位的 RTP 数据传递给 Android、iOS 和 Windows 播放器。我现在正在做 Android 部分。我发现 exoplayer 非常好用并试了一下。所以是的,这是一个 NDK 设置。
    • 其实我选择 exoplayer 的原因是因为我也在使用 React Native 来控制这些视频在 Android、iOS 和 Windows 上的显示。在 Android 上,这个 React Native 库使用 exoplayer,所以这就是我选择它的原因。
    • 如果我要使用媒体编解码器,我必须重写github.com/react-native-community/react-native-video的android部分,所以我认为最好的方法是用C++创建一个FLV数据包并将它传递给exoplayer并希望iOS 和 Windows 播放器也支持这种容器格式
    • 此外,从长远来看,FLV 支持很可能会被放弃,因为没有人再使用闪存了。这些天我看到很多webm。 Matroska 不是很好的容器格式吗?
    • 查看预期的正确 FLV 字节的最简单方法是使用 FFmpeg 从 NALU 创建一个短字节。还有一份FLV 规范 的PDF 供参考。如果您需要指导,请分享几秒钟的 NALU 链接。是的,Flash Player 浏览器插件正在消亡,但这不是一个网页项目,您只是在使用 FLV,因为它是一种易于设置的文件格式,支持 h264 编解码器并且与 h264 的顺序相同帧被打包(例如;可以实时附加),...
    【解决方案2】:

    我做了一些非常相似的事情,你可以查看我的博客文章关于自定义 ExoPlayer 的一些方面 (https://medium.com/@mahmoud.mohamed.bahaa/diving-into-exoplayer-getting-more-control-over-the-framework-cac436d1472c)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 2015-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多