视频编码

功能介绍

通过构造VideoEncoder类实例可实现视频编码功能,编码功能配置项及各项约束与支持情况请参考VideoEncodeConfig”章节

视频编码支持自定义输出数据格式,通过自定义回调函数传入编码功能配置项,方便用户使用编码后的数据,详情可参考VencCallBacker类”章节

视频编码接口说明请参考VideoEncoder

接口调用流程

首先根据需求定义需要的输出数据组合方式,根据组合方式参考VencCallBacker定义回调函数传入编码功能配置项,然后实例化VideoEncoder类,最后调用encode成员函数完成编码,获取数据。

视频编码接口调用流程参考如下:

图1 视频编码接口调用流程

Vision SDK提供VideoEncoder类进行视频编码,关键步骤说明如下:

  1. 调用mx_init()接口进行全局初始化。
  2. 定义输出数据组合形式。
    • 输出数据包含视频帧编码后得到的Image类数据、当前编码帧的“frameId”和通道“channelId”
    • 根据需要选择获取以上哪些数据。
  3. 定义输出回调函数。
    • 根据要获取的数据定义回调函数,在函数内组装自定义数据。
    • 回调函数输入参数固定为callback_func形式,函数内可选择输出。

      请勿在回调函数内实现过于复杂的操作,建议使用自定义“userData”来接收视频编码回调结果,否则回调线程会发生卡住的现象,导致视频编码速度变慢。

  4. 构造视频编码配置项。

    配置项及各项约束与支持情况请参考VideoEncodeConfig数据结构说明。

  5. 实例化视频编码类。

    将配置好的VideoEncodeConfig传入构造函数接口,实例化视频编码类。

  6. 调用encode接口对视频进行编码。
  7. 调用mx_deinit()接口进行去初始化。

示例代码

如下提供关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import os
import numpy as np
import time
from mindx.sdk import base
from mindx.sdk.base import Image, ImageProcessor
from mindx.sdk.base import VideoEncoder, VideoEncodeConfig, VencCallBacker 

# 视频编码回调函数  
def venc_callback(pyChar, outDataSize, channelId, frameId):
    with open('video_save_data/output.h264', 'ab') as file:  
        file.write(pyChar)
  
def process():
    # 初始化VencCallBacker类并注册回调函数  
    vencCallBacker = VencCallBacker()  
    vencCallBacker.registerVencCallBack(venc_callback)  
    # 初始化VideoEncodeConfig  
    venc_conf = VideoEncodeConfig()  
    venc_conf.keyFrameInterval = 50  #I帧间隔。
    venc_conf.srcRate = 30  #输入码流帧率,单位fps。
    venc_conf.maxBitRate = 6000  #输出码率,单位kbps。
    venc_conf.ipProp = 30  #一个GOP内单个I帧bit数和单个P帧bit数的比例。
    venc_conf.rcMode = 0  #指定码率控制模式。 cbr 0或1, vbr 2, avbr 3, qvbr 4, cvbr 5
    venc_conf.sceneMode = 0  # 0 摄像机不运动或周期性连续运动的场景,支持h.264/h.265, 1, 高码率下运动场景,支持h.265
    venc_conf.displayRate = 30 #输出视频的播放帧率
    venc_conf.shortTermStatsTime = 40  # 码率短期统计时间,以秒为单位 取值范围:[1, 120]。rcMode=5时生效
    venc_conf.longTermStatsTime = 240  # 码率长期统计时间,默认为分钟。取值范围:[1, 1440]。rcMode=5时生效
    venc_conf.longTermMaxBitRate = 200  # 编码器输出长期最大码率,以kbps为单位。取值范围:[2, max_bit_rate]。rcMode=5时生效
    venc_conf.longTermMinBitRate = 1  # 编码器输出长期最小码率,以kbps为单位。取值范围:[0, long_term_max_bit_rate] 。rcMode=5时生效
    venc_conf.SetThresholdI(threshold_i=[0, 0, 0, 0, 3, 3, 5, 5, 8, 8, 8, 15, 15, 20, 25, 25])
    venc_conf.SetThresholdP(threshold_p=[0, 0, 0, 0, 3, 3, 5, 5, 8, 8, 8, 15, 15, 20, 25, 25])
    venc_conf.SetThresholdB(threshold_b=[0, 0, 0, 0, 3, 3, 5, 5, 8, 8, 8, 15, 15, 20, 25, 25])
    venc_conf.direction = 8 #在基于纹理宏块级码率控制时,用于控制加减方向。
    venc_conf.rowQpDelta = 1 #行级码率控制调节幅度是一帧内行级调节的最大范围,其中行级以宏块行为单位。调节幅度越大,允许行级调整的QP范围越大,码率越平稳。
    venc_conf.firstFrameStartQp = 32 #设置第一帧的起始Qp值
    # 初始化VideoEncoder  
    videoEncoder = VideoEncoder(venc_conf, vencCallBacker, device_id)  
    # 将编码后数据保存为本地视频,若视频文件已存在则删除  
    venc_save_path = os.path.join(save_path, 'output.h264')  
    video_encode_exists = os.path.exists(venc_save_path)  
    if video_encode_exists:  
        os.remove(venc_save_path)  
    # 从decoded_data_list中循环取Image类进行编码  
    for i, img in enumerate(decoded_data_list):  
        videoEncoder.encode(img, i) 

if __name__ == "__main__":
    base.mx_init()    # 资源初始化
    process()
    base.mx_deinit()  # 资源去初始化