在Android中解码Raw H264流?

问题描述 投票:32回答:3

我有一个项目,我被要求在android中显示视频流,流是原始H.264,我连接到服务器,将从服务器接收字节流。

基本上我想知道有没有办法将原始字节发送到android中的解码器并将其显示在表面上?

我使用android 4.1中的新MediaCodec和MediaExtractor API成功解码了包含在mp4容器中的H264,遗憾的是我还没有找到使用这些API解码原始H264文件或流的方法。

我知道一种方法是编译和使用FFmpeg,但我宁愿使用可以使用硬件加速的内置方法。我也理解Android中支持RTSP流,但这不是一个选项。 Android版本不是问题。

android ffmpeg h.264 rtsp decoding
3个回答
29
投票

不幸的是,我不能为此提供任何代码,但我会尽力根据我如何使用它来解释它。

所以这里是我对如何使用MediaCodec类获得原始H.264编码视频的概述。

使用上面的链接有一个获取解码器设置以及如何使用它的示例,您需要将其设置为解码H264 AVC。

H.264的格式是它由NAL单元组成,每个NAL单元的起始前缀为三个字节,值为0x00,0x00,0x01,每个单元的类型不同,具体取决于这些后面的第4个字节的值。 3个起始字节。一个NAL单元不是视频中的一个帧,每个帧由许多NAL单元组成。

基本上我写了一个方法,找到每个单独的单元并将其传递给解码器(一个NAL单元是起始前缀,其后是任何字节,直到下一个起始前缀)。

现在,如果你有解码器设置解码H.264 AVC并从解码器有一个InputBuffer,那么你就准备好了。您需要使用NAL单元填充此InputBuffer并将其传递回解码器并继续对流的长度执行此操作。但是,为了完成这项工作,我必须先将解码器传递给SPS(序列参数集)NAL单元。在启动前缀(第4个字节)之后,该单元的字节值为0x67,在某些设备上解码器会崩溃,除非它首先接收到该单元。基本上直到找到这个单元,忽略所有其他NAL单元并继续解析流直到你得到这个单元,然后你可以将所有其他单元传递给解码器。

有些设备首先不需要SPS,有些设备确实需要SPS,但最好先将它传递给它。

现在,如果你有一个表面,你在配置它时传递给解码器,那么一旦它获得足够的NAL单位的帧,它应该在表面上显示它。


1
投票

以下是我在类似项目中发现有用的资源:

  1. This video在理解MediaCodec如何在高级别上处理原始h.264流时非常有洞察力。
  2. This thread详细介绍了处理SPS / PPS NALU的细节。如上所述,您需要使用开始前缀分隔各个NAL单元,然后将剩余数据传递给MediaCodec。
  3. This repo(libstreaming)是使用RTSP / RTP进行传输解码Android中的H264流的一个很好的例子。

-1
投票

您可以从服务器下载原始H.264,然后通过手机上运行的本地HTTP服务器提供它,然后让VLC for Android从该HTTP服务器进行播放。您应该使用VLC的http / h264://方案强制解复用器使用原始H.264(如果您不强制解复用器VLC可能无法识别流,即使HTTP服务器返回的MIME类型是设置正确)。看到

https://github.com/rauljim/tgs-android/blob/integrate_record/src/com/tudelft/triblerdroid/first/VideoPlayerActivity.java#L211

有关如何创建将启动VLC的Intent的示例。

注意:原始H.264显然没有时序信息,因此VLC将尽可能快地播放。首先将其嵌入MPEGTS会更好。还没有找到能够做到这一点的Android库。

© www.soinside.com 2019 - 2024. All rights reserved.