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的编码器,需要这样处理:
#videoscale
videoconvert ! videoscale ! "video/x-raw, format=NV12, width=1920, height=1080" ! videoconvert
#videobox
videoconvert ! videobox bottom=-8 !
3.2 事实上,我们必须重新编译特定编码器的h264encoder,认为改变h264.PPS,把这个参数传入硬件h264encoder
关于视频填充边框和透明色控制:
- gstreamer videobox中有添加透明色,填充边框的方法。
- h264流没有透明色机制,即使设置为绿色,全透明或者不透明,也无法让播放软件自动识别到视频的实际尺寸。
- 可能的控制点只能在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 originGObject
+—-GInitiallyUnowned
+—-GstObject
+—-GstElement
+—-GstVideoEncoder
+—-GstMppEnc
+—-GstMppH264Enc实现的接口:
GstPresetPad 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 参考:
- mpp – gstreamer 手册 rockchip_user_guide_linux_gstreamer_en.pdf
gstmpph264enc.c - RK平台 MPP 与RGA ,解码h265绿屏,花屏解决方法_mpp convertdata-CSDN博客
- RK-MPP硬件编解码库介绍和使用_rk mpp-CSDN博客
- rk3588音视频硬件编解码技术资料(未下载)
- RK3399Pro入门教程(6)硬件编解码器MPP库的使用 – 瑞芯微Rockchip开发者社区 – 电子技术论坛 – 广受欢迎的专业电子论坛!(未细看)
- 收缩关键字:mpp hor_stride ver_stride gstream
- H265解码与H264解码后的MppFrame编码成JPG的问题 · Issue #147 · rockchip-linux/mpp · GitHub
- videobox of gstreamer
- 在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非标准流的演示程序:
import subprocess
# 定义输出文件名
output_file = '/tmp/output.h264'
# 使用ffmpeg生成1920x1088的视频流
subprocess.run([
'ffmpeg',
'-f', 'lavfi', # 使用lavfi,生成视频流
'-i', 'testsrc2=size=1920x1088:rate=30', # 生成1920x1088的测试视频
'-vf', 'crop=1920:1080', # 裁剪到1920x1080
'-vcodec', 'libx264', # 使用H264编码
'-s', '1920x1080', # 设置SPS/PPS为1920x1080
'-pix_fmt', 'yuv420p', # 设置像素格式
'-an', # 不生成音频
output_file
])
print(f"生成的视频文件为: {output_file}")
C.1视频流属性:
可以看到它的视频分辨率和缓冲分辨率不同: