如何在 Android exoplayer 中播放原始 NAL 单元?

How to play raw NAL units in Android exoplayer?

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

我找到了 decode RTP packets using live555 and extract its NAL units. According to ExoPlayer's documentation 的方法:

Components common to all ExoPlayer implementations are:

A MediaSource that defines the media to be played, loads the media, and from which the loaded media can be read.

A MediaSource is injected via ExoPlayer.prepare at the start of playback. ...

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

class reference for MediaSource we can see that there are already some MediaSources available. I though maybe SmoothStreaming MediaSource 可以工作,但没有描述它到底做了什么,在它的构造函数中我必须提供一个 Uri 或一个 SsManifest (什么)。

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

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

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

更新:

我一直在研究这个库是如何工作的。这一切都以 MediaSource which have objects like Extractor and DataSource. Seems that ExtractorMediaSource 开头,是一个 MediaSource,您可以在其中提供自己的 ExtractorDataSource

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

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

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

所以 Extractor 以某种方式从 DataSource 读取,解析并以通用格式发送到 Renderer

我需要知道这种通用格式是怎样的,以便我可以解析从自定义 DataSource.

读取的 NAL 单元

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

不清楚你神秘的C++代码在做什么,是NDK setup? What's its role in Android decoding? Are you saying you're unable to pass [from the C++ function] a data array into some Android function as function parameter? Is it something like this Java to C++ setup吗?不清楚你真正的问题是什么...

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

作为第二个选项,对于 Android,您可以只使用 MediaCodec to decode the H264 as extracted from the NAL units. Here is a useful example source。只需用作:

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

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

其他起点:

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