在Android中解码Raw H264流?

时间:2012-11-09 11:16:48

标签: android ffmpeg h.264 rtsp decoding

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

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

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

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

3 个答案:

答案 0 :(得分: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)

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

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

答案 2 :(得分:-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库。