利用DVPP的VENC对视频进行编码没有结果
收藏回复举报
利用DVPP的VENC对视频进行编码没有结果
t('forum.solved') 已解决
发表于2025-01-16 16:52:50
0 查看

true

Your Code
# coding:utf-8
import time

import acl
import cv2
import numpy as np
import subprocess


def t_g(frame):
    # 获取图像的高、宽
    height, width, _ = frame.shape

    # 将 BGR 图像转换为 YUV 格式
    yuv = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV)

    # 创建一个大小为 height + height//2 和 width 的空数组来存储 YUV420SP (NV12) 格式
    yuv420sp = np.zeros((height + height // 2, width), dtype=np.uint8)

    # Y 分量:直接将 Y 分量拷贝到 yuv420sp 中
    yuv420sp[:height, :] = yuv[:, :, 0]

    # UV 分量(NV12格式,U和V交替排列)
    u = yuv[:, :, 1]
    v = yuv[:, :, 2]

    # 将 U 和 V 分量合并为一个交替存储的格式(NV12:U和V交替)
    yuv420sp[height:, ::2] = u[::2, ::2]  # U 分量
    yuv420sp[height:, 1::2] = v[::2, ::2]  # V 分量
    return yuv420sp


memcpy_kind = {
    "ACL_MEMCPY_HOST_TO_HOST": 0,
    "ACL_MEMCPY_HOST_TO_DEVICE": 1,
    "ACL_MEMCPY_DEVICE_TO_HOST": 2,
    "ACL_MEMCPY_DEVICE_TO_DEVICE": 3
}


# 1. pyACL 初始化
ret = acl.init()
acl.rt.set_device(0)


# 2. 获取软件栈的运行模式
run_mode, ret = acl.rt.get_run_mode()
print(f"run_mode is >>>>>>>>> {run_mode},ret >>>>>>>>>>> {ret}")
# 3. 运行管理资源申请
# 4. 初始化媒体数据处理系统
ret = acl.himpi.sys_init()
# 5. 设置 VENC 模块参数
param = {'mod_type': 2 ,  # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0651.html
         'h264_mod_param':{ # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0653.html
             "one_stream_buf":1,
             "mini_buf_mode":1,
             "low_power_mode":1,
             "vb_src":2,
             "qp_hist_en":1,
             "max_user_data_len":1024
         }
         }

param, ret = acl.himpi.venc_get_mod_param(param)
# param['jpeg_mod_param']['one_stream_buf'] = 1
ret = acl.himpi.venc_set_mod_param(param)

# 6. 创建编码通道
channel_id = 0
venc_attr = {
    # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0616.html
    'type': 96,
    # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0562.html
    'profile': 0,
    'max_pic_width': 1280,
    'pic_width': 1280,
    'max_pic_height': 720,
    'pic_height': 720,
    'buf_size': 5 * 1024 * 720,
    'is_by_frame': 1,
    "h264_attr": {
        "rcn_ref_share_buf_en": 0,
        "frame_buf_ratio": 80
    }
}
rc_attr = {
    # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0617.html
    'rc_mode': 2,
    # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0618.html
    'h264_vbr':  # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0619.html
        {'gop': 30, 'stats_time': 1, 'src_frame_rate': 30, 'dst_frame_rate': 30, 'max_bit_rate': 2000}
}
gop_attr = {'gop_mode': 0, 'normal_p': {'ip_qp_delta': -1}}
attr = {'venc_attr': venc_attr, 'rc_attr': rc_attr, 'gop_attr': gop_attr}
ret = acl.himpi.venc_create_chn(channel_id, attr)

# 7. 通知编码器开始接收输入数据
recv_param = {'recv_pic_num': -1}
ret = acl.himpi.venc_start_chn(channel_id, recv_param)
print('[INFO] venc_start_chn', ret)

# 8. 设置 RTSP 推流
# rtsp_url = "rtsp://127.0.0.1:8554/video"
# ffmpeg_process = subprocess.Popen([
#     "ffmpeg",
#     "-y", "-f", "rawvideo",
#     "-pix_fmt", "yuv420p",
#     "-s", "1280x720",
#     "-i", "-",
#     "-c:v", "libx264",
#     "-f", "rtsp",
#     rtsp_url
# ], stdin=subprocess.PIPE)

# 9. 捕获摄像头帧并编码推流
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap.set(cv2.CAP_PROP_FPS, 30)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc(*"MJPG"))  # 设置宽度
cap.set(cv2.CAP_PROP_FPS, 120)
cap.set(cv2.CAP_PROP_AUTO_WB, 1.0)  # 打开自动白平衡
for i in range(40):
    cap.read()
    time.sleep(1000 / 25 / 1000)  # 目的是为了清掉相机里白平衡的数据?
cap.set(cv2.CAP_PROP_GAIN, 255)
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 3.0)  # 打开自动曝光 (相机会记住曝光)
fd = acl.himpi.venc_get_fd(channel_id)
# epoll_fd, ret = acl.himpi.sys_create_epoll(10)
# print('[INFO] sys_create_epoll', ret)
# https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0577.html
# event = {'data': fd, 'events': 1}
# https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0576.html
# ret = acl.himpi.sys_ctl_epoll(epoll_fd, 1, fd, event)
# print('[INFO] sys_ctl_epoll', ret)
# https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclpythondevg_01_0421.html
while True:
    ret, frame = cap.read()
    if not ret:
        break
    print('[DEBUG] Frame shape:', frame.shape)
    # 转换为 YUV420 格式
    frame_yuv = t_g(frame)
    input_size = frame_yuv.nbytes    
    input_addr, ret = acl.himpi.dvpp_malloc(0, input_size)
    bytes_data = frame_yuv.tobytes()
    frame_ptr = acl.util.bytes_to_ptr(bytes_data)
    # acl.rt.get_run_mode接口获取软件栈的运行模式为ACL_DEVICE,则直接申请Device内存,存放输入图片数据   
    ret = acl.rt.memcpy(input_addr, input_size, frame_ptr, input_size, memcpy_kind['ACL_MEMCPY_DEVICE_TO_DEVICE'])


    # 创建编码帧结构
    v_frame = {
        'width': 1280, 'height': 720,
        'field': 0x4,
        # https://www.hiascend.com/document/detail/zh/Atlas200IDKA2DeveloperKit/23.0.RC2/Application%20Development%20Guide/aadgp/aclpythondevg_01_0549.html
        'pixel_format': 1,
        # https://www.hiascend.com/document/detail/zh/Atlas200IDKA2DeveloperKit/23.0.RC2/Application%20Development%20Guide/aadgc/aclcppdevg_03_1093.html
        'video_format': 0,
        # https://www.hiascend.com/document/detail/zh/Atlas200IDKA2DeveloperKit/23.0.RC2/Application%20Development%20Guide/aadgc/aclcppdevg_03_1104.html
        'compress_mode': 0,
        # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclcppdevg_03_0804.html
        'dynamic_range': 0,
        # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/apiref/appdevgapi/aclcppdevg_03_0777.html
        'color_gamut': 1,
        # https://www.hiascend.com/document/detail/zh/Atlas200IDKA2DeveloperKit/23.0.RC2/Application%20Development%20Guide/aadgp/aclpythondevg_01_0551.html
        'width_stride': [1280, 0, 0],
        'virt_addr': [input_addr, 0, 0],
        'header_stride': [0, 0, 0],
        'height_stride': [0, 0, 0],
        'header_phys_addr': [0, 0, 0],
        'phys_addr': [0, 0, 0],
        'header_virt_addr': [0, 0, 0],
        'time_ref': 0, 'pts': 123
    }
    frame = {'v_frame': v_frame, 'pool_id': 0,
             'mod_id': 10}  # https://www.hiascend.com/document/detail/zh/canncommercial/80RC3/developmentguide/appdevg/ispdevug/ispdevapi_0031.html
    ret = acl.himpi.venc_send_frame(channel_id, frame, -1)
    # print('[INFO] venc_send_frame', ret)
    # time.sleep(5)
    # events, eventCount, ret = acl.himpi.sys_wait_epoll(epoll_fd, 3, 1000)
    # 获取编码结果
    # print('[INFO] sys_create_epoll', ret,events,eventCount)
    status, ret = acl.himpi.venc_query_status(channel_id)
    print('[INFO] venc_query_status', ret, status)
    # 获取编码结果
    if status['cur_packs'] > 0:
        stream = {'pack_cnt': status['cur_packs']}
        stream, ret = acl.himpi.venc_get_stream(channel_id, stream, 1000)
        if ret == 0:
            print('[INFO] venc_get_stream success')
            encoded_data = acl.util.ptr_to_bytes(stream['pack'][0]['addr'])
            # ffmpeg_process.stdin.write(encoded_data)
            ret = acl.himpi.venc_release_stream(channel_id, stream)
        else:
            print('[ERROR] venc_get_stream failed:', ret)
    else:
        print('[DEBUG] No data available in cur_packs')
    # print('[INFO] venc_query_status', ret, status)
    # stream = {'pack_cnt': status['cur_packs']}
    # stream, ret = acl.himpi.venc_get_stream(channel_id, stream, 1000)
    # print('[INFO] venc_get_stream', ret)
    # encoded_data = acl.util.ptr_to_bytes(stream['pack'][0]['addr'])
    # ffmpeg_process.stdin.write(encoded_data)
    # ret = acl.himpi.venc_release_stream(channel_id, stream)

# 10. 释放资源
cap.release()
# ffmpeg_process.stdin.close()
# ffmpeg_process.wait()

ret = acl.himpi.venc_stop_chn(channel_id)
ret = acl.himpi.venc_destroy_chn(channel_id)
ret = acl.himpi.sys_exit()
ret = acl.finalize()

我要发帖子