我在Android上使用原生MediaCodec APIs通过RTMP传输h264视频和AAC音频。视频和音频看起来很好,然而,当视频是在potrait模式下拍摄时,在网络上或用VLC播放总是在横向。
在阅读了h264规范后,我看到这种额外的元数据可以在补充增强信息(SEI)中指定,我已经着手将其添加到原始h264位流中。我的SEI NAL单元就是按照这个基本格式来做的,我打算以后再优化。
val displayOrientationSEI = {
val prefix = byteArrayOf(0, 0, 0, 1)
val nalHeader = byteArrayOf(6) // forbidden_zero_bit:0; nal_ref_idc:0; nal_unit_type:6
val display = byteArrayOf(47 /* Display orientation type*/, 3 /*payload size*/)
val displayOrientationCancelFlag = "0" // u(1); Rotation information follows
val horFlip = "1" // hor_flip; u(1); Flip horizontally
val verFlip = "1" // ver_flip; u(1); Flip vertically
val anticlockwiseRotation = "0100000000000000" // u(16); value / 2^16 -> 90 degrees
val displayOrientationRepetitionPeriod = "010" // ue(v); Persistent till next video sequence
val displayOrientationExtensionFlag = "0" // u(1); No other value is permitted by the spec atm
val byteAlignment = "1"
val bitString = displayOrientationCancelFlag +
horFlip +
verFlip +
anticlockwiseRotation +
displayOrientationRepetitionPeriod +
displayOrientationExtensionFlag +
byteAlignment
prefix + nalHeader + display + BigInteger(bitString, 2).toByteArray()
}()
使用... Jcodec的SEI类,我可以看到我的SEI消息被正确解析。我把这些数据包写到RTMP流中,用一个 LibRtmp的Android JNI封装器.
尽管如此,ffprobe并没有显示方向元数据,播放时视频仍然是横向的。
在这一点上,我认为我遗漏了一个非常小的细节,即当原始h264单元被LibRtmp写出来时,FLV头是如何工作的。我试着附加了以下内容 displayOrientationSEI
NAL装置。
我到底做错了什么?通过一些RTMP库的源码,如 rtmp-rtsp-stream-client-java。在创建FLV标签时,似乎SEI信息被删除了。
帮助是很多,非常感谢。
RTMP是否支持h264流中的显示方向SEI信息?
RTMP不知道这个概念。从RTMPs的角度来看,SEI只是一系列的字节,它复制。它从不看它们,也从不解析它们。
需要支持它的东西,是h.264解码器(RTMP也不知道)和播放器软件。如果它不为你工作,你必须检查播放器,或编码SEI的有效性,而不是传输。