瑞芯微系列 video stream out的一些基础知识

随笔2周前发布 汐桃
31 0 0

1.原始pic及视频流生成

如果来自AI的训练结果,这个一般是3通道的RGB模式,所以:

videoparse format=bgr width=1920 height=1088 ! videoconvert

2.编码器的输入存储分辨率和格式的的考量:

如果使用mpph264enc这类硬编码器,因为所有编码器的输入流都是比如YUV格式,需要明确视频流输入的格式:

! videoconvert ! video/x-raw, format=NV12, width=1920, height=1088 

3. 但是上面那个是缓冲分辨率,怎么将显示分辨率的信息放进去呢?

3.1 额外的图形分辨率处理

对于videobox,正值是消除,负值是增加Positive values will crop that much pixels from the respective border of the image, negative values will add that much pixels

所以,对于针对1920*1080图片,实际需要原始YUV图像需要扩展到1920.1088的编码器,需要这样处理:

  1. #videoscale

  2. videoconvert ! videoscale ! "video/x-raw, format=NV12, width=1920, height=1080" ! videoconvert

  3. #videobox

  4. videoconvert ! videobox bottom=-8 !

3.2 事实上,我们必须重新编译特定编码器的h264encoder,认为改变h264.PPS,把这个参数传入硬件h264encoder

关于视频填充边框和透明色控制:

  1.  gstreamer videobox中有添加透明色,填充边框的方法。
  2. h264流没有透明色机制,即使设置为绿色,全透明或者不透明,也无法让播放软件自动识别到视频的实际尺寸。
  3. 可能的控制点只能在h264的pps, sps数据。

=>尝试能否找到rk3588的mpph264enc源码。

在mpph264enc中的确没有其他的分辨率调整标记:

3.2.1 mpph264enc接口说明

kde@ai:/tmp$ gst-inspect-1.0 mpph264enc
Factory Details:
  Rank                     primary + 1 (257)
  Long-name                Rockchip Mpp H264 Encoder
  Klass                    Codec/Encoder/Video
  Description              Encode video streams via Rockchip Mpp
  Author                   Randy Li <randy.li@rock-chips.com>, Jeffy Chen <jeffy.chen@rock-chips.com>

Plugin Details:
  Name                     rockchipmpp
  Description              Rockchip Mpp Video Plugin
  Filename                 /usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstrockchipmpp.so
  Version                  1.14.4
  License                  LGPL
  Source module            gst-rockchip
  Binary package           GStreamer Rockchip Plug-ins
  Origin URL               Unknown package origin

GObject
 +—-GInitiallyUnowned
       +—-GstObject
             +—-GstElement
                   +—-GstVideoEncoder
                         +—-GstMppEnc
                               +—-GstMppH264Enc

实现的接口:
  GstPreset

Pad Templates:
  SINK template: ‘sink’
    Availability: Always
    Capabilities:
      video/x-raw
                 format: { (string)NV12, (string)I420, (string)YUY2, (string)UYVY, (string)BGR16, (string)RGB16, (string)ABGR, (string)ARGB, (string)BGRA, (string)RGBA, (string)xBGR, (string)xRGB, (string)BGRx, (string)RGBx, (string)NV12, (string)NV21, (string)I420, (string)YV12, (string)NV16, (string)NV61, (string)BGR16, (string)RGB, (string)BGR, (string)RGBA, (string)BGRA, (string)RGBx, (string)BGRx }
                  width: [ 96, 2147483647 ]
                 height: [ 64, 2147483647 ]

  
  SRC template: ‘src’
    Availability: Always
    Capabilities:
      video/x-h264
                  width: [ 96, 2147483647 ]
                 height: [ 64, 2147483647 ]
          stream-format: { (string)byte-stream }
              alignment: { (string)au }
                profile: { (string)baseline, (string)main, (string)high }

Element has no clocking capabilities.
Element has no URI handling capabilities.

Pads:
  SINK: ‘sink’
    Pad Template: ‘sink’
  SRC: ‘src’
    Pad Template: ‘src’

Element Properties:
  arm-afbc            : Input is ARM AFBC compressed format
                        flags: 可读, 可写
                        Boolean. Default: false
  bps                 : Target BPS (0 = auto calculate)
                        flags: 可读, 可写
                        Unsigned Integer. Range: 0 – 2147483647 Default: 0 
  bps-max             : Max BPS (0 = auto calculate)
                        flags: 可读, 可写
                        Unsigned Integer. Range: 0 – 2147483647 Default: 0 
  bps-min             : Min BPS (0 = auto calculate)
                        flags: 可读, 可写
                        Unsigned Integer. Range: 0 – 2147483647 Default: 0 
  gop                 : Group of pictures starting with I frame (-1 = FPS, 1 = all I frames)
                        flags: 可读, 可写
                        Integer. Range: -1 – 2147483647 Default: -1 
  header-mode         : Header mode
                        flags: 可读, 可写
                        Enum “MppEncHeaderMode” Default: 0, “first-frame”
                           (0): first-frame      – Only in the first frame
                           (1): each-idr         – In every IDR frames
  level               : H264 level (40~41 = 1080p@30fps, 42 = 1080p60fps, 50~52 = 4K@30fps)
                        flags: 可读, 可写
                        Enum “GstMppH264Level” Default: 40, “4”
                           (10): 1                – 1
                           (99): 1b               – 1b
                           (11): 1.1              – 1.1
                           (12): 1.2              – 1.2
                           (13): 1.3              – 1.3
                           (20): 2                – 2
                           (21): 2.1              – 2.1
                           (22): 2.2              – 2.2
                           (30): 3                – 3
                           (31): 3.1              – 3.1
                           (32): 3.2              – 3.2
                           (40): 4                – 4
                           (41): 4.1              – 4.1
                           (42): 4.2              – 4.2
                           (50): 5                – 5
                           (51): 5.1              – 5.1
                           (52): 5.2              – 5.2
                           (60): 6                – 6
                           (61): 6.1              – 6.1
                           (62): 6.2              – 6.2
  max-reenc           : Max re-encode times for one frame
                        flags: 可读, 可写
                        Unsigned Integer. Range: 0 – 3 Default: 1 
  min-force-key-unit-interval: Minimum interval between force-keyunit requests in nanoseconds
                        flags: 可读, 可写
                        Unsigned Integer64. Range: 0 – 18446744073709551615 Default: 0 
  name                : The name of the object
                        flags: 可读, 可写, 0x2000
                        String. Default: “mpph264enc0”
  parent              : The parent of the object
                        flags: 可读, 可写, 0x2000
                        Object of type “GstObject”
  profile             : H264 profile
                        flags: 可读, 可写
                        Enum “GstMppH264Profile” Default: 100, “high”
                           (66): baseline         – Baseline
                           (77): main             – Main
                           (100): high             – High
  qos                 : Handle Quality-of-Service events from downstream
                        flags: 可读, 可写
                        Boolean. Default: false
  qp-init             : Initial QP (lower value means higher quality)
                        flags: 可读, 可写
                        Unsigned Integer. Range: 0 – 51 Default: 26 
  qp-max              : Max QP (0 = default)
                        flags: 可读, 可写
                        Unsigned Integer. Range: 0 – 51 Default: 0 
  qp-max-step         : Max delta QP step between two frames (-1 = default)
                        flags: 可读, 可写
                        Integer. Range: -1 – 51 Default: -1 
  qp-min              : Min QP (0 = default)
                        flags: 可读, 可写
                        Unsigned Integer. Range: 0 – 51 Default: 0 
  rc-mode             : RC mode
                        flags: 可读, 可写
                        Enum “GstMppEncRcMode” Default: 1, “cbr”
                           (0): vbr              – Variable bitrate
                           (1): cbr              – Constant bitrate
                           (2): fixqp            – Fixed QP
  sei-mode            : SEI mode
                        flags: 可读, 可写
                        Enum “GstMppEncSeiMode” Default: 0, “disable”
                           (0): disable          – SEI disabled
                           (1): one-seq          – One SEI per sequence
                           (2): one-frame        – One SEI per frame(if changed)
  zero-copy-pkt       : Zero-copy encoded packet
                        flags: 可读, 可写
                        Boolean. Default: true


附录A 参考:

  1. mpp – gstreamer 手册 rockchip_user_guide_linux_gstreamer_en.pdf
    gstmpph264enc.c 
  2. RK平台 MPP 与RGA ,解码h265绿屏,花屏解决方法_mpp convertdata-CSDN博客
  3. RK-MPP硬件编解码库介绍和使用_rk mpp-CSDN博客
  4. rk3588音视频硬件编解码技术资料(未下载)
  5. RK3399Pro入门教程(6)硬件编解码器MPP库的使用 – 瑞芯微Rockchip开发者社区 – 电子技术论坛 – 广受欢迎的专业电子论坛!(未细看) 
  6. 收缩关键字:mpp hor_stride ver_stride gstream
  7. H265解码与H264解码后的MppFrame编码成JPG的问题 · Issue #147 · rockchip-linux/mpp · GitHub
  8. videobox of gstreamer
  9. 在rk3588平台快速使用硬件编解码功能_专栏_易百纳技术社区 – mpph264enc接口查看

附录B  关于Encoding阶段构建h264非标准包的讨论

>>>有没有可能一个.h264流实际上的帧是1088行,但是它的格式字段却标明了它是全高清?1080行?

在 H.264 编码的流中,确实可以出现这种情况,即视频流的实际帧高度与格式字段中标明的分辨率不一致。这通常发生在以下几种情况下:

1. 编码器设置与实际帧
实际分辨率与标明的分辨率:编码器可能会将视频帧编码为实际分辨率(如 1920×1088),但在流的格式字段中(如 SPS/PPS 中),它可能标明了标准的分辨率(如 1920×1080)。这种情况下,实际的帧尺寸与格式信息中的尺寸可能不匹配。
2. 流的处理与封装
封装格式:某些容器格式或流可能允许以自定义方式处理或封装视频数据。例如,流可能会被处理成带有不同分辨率数据的帧,播放器或处理工具会依照封装格式来进行处理。
3. 播放器或解码器行为
解码器处理:解码器在解码时会依据格式字段来处理帧,但可能会遇到实际帧尺寸与标明尺寸不符的情况。通常,解码器会根据流中的格式信息进行解码,然后可能会裁剪或调整实际帧以符合标明的分辨率。
4. 例外情况
填充行(Padding):有时编码器会添加填充行来对齐帧大小。实际的数据可能会包含额外的行(如 1920×1088),而格式字段可能指定了标准的有效帧(1920×1080)。这些填充行通常会在后处理时被裁剪掉。
实际应用场景
标准化视频流:在处理视频流时,可能会出现实际帧尺寸与标准分辨率不一致的情况。为了保证一致性,通常会在后期处理时将视频调整为符合标称分辨率的标准。例如,某些视频编辑和处理工具会自动裁剪或调整帧以匹配目标分辨率。

多种分辨率数据:有时,流中可能包含不同分辨率的帧数据,特别是在复杂的流封装和传输情况下。解码和播放这些流时,实际的帧尺寸会受到处理和调整的影响。

结论
总结来说,H.264 视频流的实际帧尺寸和格式字段中的分辨率可能存在不一致的情况。这种情况下,格式字段通常标明了标准或期望的分辨率,而实际帧可能需要进行裁剪或调整,以符合实际应用的要求。

>>>我怎么才能用gstreamer来构建一个这样的非标准化信息流?

要使用 GStreamer 构建一个具有非标准化信息流(如实际帧分辨率与格式字段指定的分辨率不匹配)的流,你可以通过自定义参数和元素的组合来实现。以下是一些关键步骤和 GStreamer 命令行示例,说明如何进行设置。

步骤概述
配置视频源:选择一个合适的输入视频源,例如 videotestsrc(测试视频生成器)或使用 rtspsrc 读取实时流。
设置编码器:选择适合的编码器来输出 H.264 格式,并设置帧宽高比。
插入虚拟帧:使用 tiledvideosink 或其他元素来让输出帧具有非标准化的分辨率。
使用 h264parse 来操控格式字段:在传输过程中插入或处理数据,确保流中的某些信息是非标准化的。
示例 GStreamer 管道
假设你想要生成一个 1920×1088 分辨率的视频流(即包含两行填充)但标明输出为 1920×1080,并通过 appsink 输出:

gst-launch-1.0 videotestsrc ! video/x-raw,width=1920,height=1088 ! videoconvert ! x264enc ! h264parse ! video/x-h264,stream-format=byte-stream ! appsink
详细配置示例
下面是更复杂的使用 GStreamer 构建非标准化 H.264 流的 Pipeline 示例:

gst-launch-1.0 -e
videotestsrc ! video/x-raw,width=1920,height=1088 !
videoconvert ! x264enc tune=zerolatency !
h264parse !
rtph264pay config-interval=1 pt=96 !
udpsink host=127.0.0.1 port=5000
说明
videotestsrc:这是一个测试视频源,生成一个简单的模式作为输入。
video/x-raw,width=1920,height=1088:指定原始视频帧的分辨率为 1920×1088。
videoconvert:转换视频格式,以确保下游元素可以正确处理。
x264enc:使用 H.264 编码器编码视频流。你可以通过设置不同的参数来调整编码选项。
h264parse:分析 H.264 流并可以处理一些格式设置。特别是在其后没有加入其他元素的情况下,它可以控制流的标记和设置。
rtph264pay:将编码的 H.264 数据有效地打包以便进行 RTP 发送。
udpsink:将生成的流通过 UDP 发送到指定主机和端口。
接收和解析流
要接收这个流并验证其特性,可以使用以下命令:

gst-launch-1.0 udpsrc port=5000 ! application/x-rtp,payload=96 ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink
自定义示例
如果你想要更高级的特性,比如在数据流中强制性包含非标准的格式信息,你可能需要自定义 GStreamer 插件或在应用程序中使用 GStreamer 库,通过编程创建一个复杂的流。

额外建议
使用 GStreamer 的开发文档:GStreamer 官方文档提供了详细的 API 参考和使用例,可以帮助你构建更复杂的管道。
调试和观察流:你可以使用工具如 gst-inspect-1.0 和 gst-debug 来观察和调试你的 GStreamer 流。
这个框架应该帮助你开始构建你的非标准的视频流。如果有其他特定的需求或问题,请提供更多信息。

>>>h264parse rtph264pay中能做构建非标准化H.264的处理吗?

在 GStreamer 中,h264parse 和 rtph264pay 主要用于处理 H.264 编码数据的解析和打包。虽然它们有助于管理和传输 H.264 流,但它们本身不提供直接的方式来构建非标准化的 H.264 数据流。下面详细说明它们的功能以及如何在整个管道中实现非标准化流。

1. h264parse 的功能
解析 H.264 流:h264parse 可以从 H.264 编码流中解析出 SPS(序列参数集)、PPS(图像参数集)等信息,并进行必要的格式转换。
处理码流:适用于切割、重包装 H.264 数据流,以确保数据的有效性和兼容性。
限制:它不会改变帧的分辨率或格式字段信息,它只负责格式的解析和流的组织。
2. rtph264pay 的功能
打包 RTP 数据包:rtph264pay 将解析后的 H.264 数据打包成 RTP 格式,适合通过网络传输。
基本处理:它不会改变原始数据的编码格式或帧的信息,只会将其封装为 RTP 数据包,这一过程通常是为了解析和传递数据。
3. 构建非标准化 H.264 流
要实现非标准化的 H.264 数据流,你可以采取以下策略:

使用自定义元素或应用程序中的处理:

通过在自己的代码中使用 GStreamer 库,创建一个自定义元素来强制改变 SPS/PPS 的设置,或者调整编码参数来生成你需要的非标准化流。
例如,你可以修改 SPS 的高度信息来表示 1080 行,但实际编码为 1088 行的内容。
调整编码器设置:

使用 x264enc(或其他编码器)时,确保它配置为输出所需的实际分辨率,然后手动调整 SPS/PPS 内容。如果只修改编码流的元数据,而不是真正编码的内容,后续的 h264parse 不会逆向这个过程。
自定义处理管道:

在管道中引入自定义的转换元素,这些元素能够调整数据流以生成你想要的非标准格式,或者直接操纵输出的 H.264 码流。
示例代码
以下是一个示例 GStreamer 管道,它展示了如何构建流,但请注意,在这个简单的示例中,h264parse 和 rtph264pay 并没有直接提供构建非标准流的功能。

gst-launch-1.0 -e
videotestsrc ! video/x-raw,width=1920,height=1088 !
videoconvert ! x264enc ! h264parse !
rtph264pay ! udpsink host=127.0.0.1 port=5000
总结
h264parse 和 rtph264pay 本身无法单独做构建非标准化的信息流的处理,它们主要负责数据解析和打包。
若要创建非标准化 H.264 流,需要通过 定制编码器设置、修改 SPS/PPS 信息,或是实现自定义 GStreamer 元素 来实现。
如果你希望在 H.264 流中覆盖某些字段(例如标明其格式的字段与实际流不符),则可能需要进行自定义开发,利用 GStreamer 的插件机制来达到目的。
这种开发可能需要深入了解 GStreamer 的内部机制和 H.264 编码标准,建议你查阅相关文档并进行实际编码测试。

>>>PPS只能在x264enc中处理,h264parse, rtph264pay是无法处理的,对吧?

是的,你的理解是正确的。在 GStreamer 中,**PPS(Picture Parameter Set)**的处理主要是在编码阶段由 x264enc 来完成,而 h264parse 和 rtph264pay 主要用于解析和打包已经编码好的 H.264 数据流,无法直接修改 PPS 或 SPS 的内容。

详细说明
x264enc 的作用:

编码和生成 PPS/SPS:x264enc 负责将原始视频数据编码为 H.264 格式,同时生成包含必要参数的 SPS 和 PPS。它会在编码过程中决定参数集的内容,比如分辨率、帧率等。
选项和参数:你可以通过设置 x264enc 的参数来影响生成的 SPS/PPS。例如,在编码时指定 max-bframes 或其他 H.264 特性从而改变生成的码流特征。
h264parse 的作用:

解析和处理:h264parse 主要用于解析 H.264 流中的 SPS 和 PPS,并能够确保流在传输和解析时的一致性。它并不负责生成或修改这些参数集。
转发原始码流:在流过 h264parse 后,元数据如 SPS 和 PPS 通常会被转发,但不进行实际的内容修改。
rtph264pay 的作用:

打包为 RTP:rtph264pay 为 RTP 协议打包 H.264 数据流,使其适合流式传输。它不会对流中的 SPS、PPS 或其他相关数据进行任何形式的修改。
仅仅封装:它的功能仅限于将流分配成 RTP 数据包,使得该数据能够通过 UDP 等协议传输。
结论
在生成和修改 H.264 数据流的 SPS/PPS 时,关键就在于使用适当的编码器,如 x264enc。一旦数据流被编码为 H.264 格式,h264parse 和 rtph264pay 将无法对其内部的 SPS/PPS 进行修改。为了实现非标准化的视频流,任何必要的调整都需要在编码阶段进行。

如果你需要特定的 SPS/PPS 参数设置,最好是在使用 x264enc 时通过其参数进行控制,而不是依赖于后续的解析或打包阶段。

附录C h264非标准流的演示程序:

  1. import subprocess

  2. # 定义输出文件名

  3. output_file = '/tmp/output.h264'

  4. # 使用ffmpeg生成1920x1088的视频流

  5. subprocess.run([

  6. 'ffmpeg',

  7. '-f', 'lavfi', # 使用lavfi,生成视频流

  8. '-i', 'testsrc2=size=1920x1088:rate=30', # 生成1920x1088的测试视频

  9. '-vf', 'crop=1920:1080', # 裁剪到1920x1080

  10. '-vcodec', 'libx264', # 使用H264编码

  11. '-s', '1920x1080', # 设置SPS/PPS为1920x1080

  12. '-pix_fmt', 'yuv420p', # 设置像素格式

  13. '-an', # 不生成音频

  14. output_file

  15. ])

  16. print(f"生成的视频文件为: {output_file}")

C.1视频流属性:

可以看到它的视频分辨率和缓冲分辨率不同:

瑞芯微系列 video stream out的一些基础知识

瑞芯微系列 video stream out的一些基础知识

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...