nowind

nowind

0个粉丝

1

问答

0

专栏

0

资料

nowind  发布于  2025-03-20 11:14:15
采纳率 0%
1个问答
119

hi3519dv500中hi_mpi_vpss_get_chn_frame的问题

利用mmp中sample的vdec示例代码,利用sample_h264_vdec_vpss_vo(), 改为输入1080p的h264文件,修改为OT_VPSS_CHN_MODE_USER模式,设置深度为3

    sample_config_vpss_grp_attr(&vpss_grp_attr); // 设置 vpss grp 参数
    (td_void) memset_s(vpss_chn_enable, arr_len * sizeof(td_bool), 0, arr_len * sizeof(td_bool));
    sample_comm_vpss_get_default_chn_attr(&vpss_chn_attr.chn_attr[0]); // 初始化VPSS物理通道值
    vpss_chn_enable[0] = TD_TRUE;
    vpss_chn_attr.chn_enable[0] = TD_TRUE;
    vpss_chn_attr.chn_array_size = OT_VPSS_MAX_CHN_NUM;
    vpss_chn_attr.chn_attr[0].depth = 3;
    vpss_chn_attr.chn_attr[0].width = g_disp_size.width;
    vpss_chn_attr.chn_attr[0].height = g_disp_size.height;
    vpss_chn_attr.chn_attr[0].chn_mode = OT_VPSS_CHN_MODE_USER; // user mode

删除 vo 相关代码后,加入保存yuv的代码

    printf("sample_start_vdec \n");

    ret = sample_start_vpss(&vpss_grp, vpss_grp_num, &vpss_chn_enable[0], OT_VPSS_MAX_CHN_NUM);
    if (ret != TD_SUCCESS)
    {
        goto stop_vdec;
    }

    printf("thread create \n");
    pthread_t thread;
    if ((ret = pthread_create(&thread, NULL, get_frame_sample, NULL)) != 0)
    {
        sample_print("Thread create failed! errno = %d\n", ret);
    }

    sample_print("asdasdasdasd \n");

    sample_send_stream_to_vdec(&sample_vdec[0], OT_VDEC_MAX_CHN_NUM, vdec_chn_num, "output.h264");

    int result = pthread_join(thread, NULL);
    if (result != 0)
    {
        sample_print("Thread join failed: %d\n", result);
    }

保存yuv相关函数代码如下:

void write_plane(FILE *fp, const uint8_t *data,
                 uint32_t width, uint32_t height,
                 uint32_t stride)
{
    for (uint32_t y = 0; y < height; y++)
    {
        const uint8_t *line_start = data + y * stride;
        if (fwrite(line_start, 1, width, fp) != width)
        {
            perror("写入数据失败");
            break;
        }
    }
}

void write_vu_as_uv(FILE *fp, const uint8_t *vu_data,
                    uint32_t width, uint32_t height,
                    uint32_t stride)
{
    uint8_t *uv_line = malloc(width);
    if (!uv_line)
    {
        perror("内存分配失败");
        return;
    }

    for (uint32_t y = 0; y < height; y++)
    {
        const uint8_t *vu_line = vu_data + y * stride;
        // 交换每个VU对为UV
        for (uint32_t x = 0; x < width; x += 2)
        {
            uv_line[x] = vu_line[x + 1]; // U
            uv_line[x + 1] = vu_line[x]; // V
        }
        if (fwrite(uv_line, 1, width, fp) != width)
        {
            perror("写入UV数据失败");
            break;
        }
    }

    free(uv_line);
}

int save_video_frame_to_yuv(const ot_video_frame *frame, const char *filename)
{
    if (!frame || !filename ||
        frame->phys_addr[0] == 0 || frame->phys_addr[1] == 0 ||
        frame->width == 0 || frame->height == 0)
    {
        fprintf(stderr, "错误:无效输入参数\n");
        return -1;
    }

    const uint32_t y_plane_size = frame->stride[0] * frame->height;
    const uint32_t uv_plane_size = frame->stride[1] * (frame->height / 2);

    uint8_t *y_virt = (uint8_t *)ss_mpi_sys_mmap(frame->phys_addr[0], y_plane_size);
    if (!y_virt)
    {
        fprintf(stderr, "错误:Y分量映射失败 (phys:0x%lx, size:%u)\n",
                frame->phys_addr[0], y_plane_size);
        return -1;
    }

    uint8_t *uv_virt = (uint8_t *)ss_mpi_sys_mmap(frame->phys_addr[1], uv_plane_size);
    if (!uv_virt)
    {
        fprintf(stderr, " UV分量映射失败 (phys:0x%lx, size:%u)\n",
                frame->phys_addr[1], uv_plane_size);
        ss_mpi_sys_munmap(y_virt, y_plane_size);
        return -1;
    }

    FILE *fp = fopen(filename, "wb");
    if (!fp)
    {
        perror("错误:文件打开失败");
        ss_mpi_sys_munmap(y_virt, y_plane_size);
        ss_mpi_sys_munmap(uv_virt, uv_plane_size);
        return -1;
    }

    write_plane(fp, y_virt, frame->width, frame->height, frame->stride[0]); // 写入 Y 分量(全分辨率)
    write_vu_as_uv(fp, uv_virt, frame->width / 2, frame->height / 2, frame->stride[1]);
    // write_plane(fp, uv_virt, frame->width / 2, frame->height / 2, frame->stride[1]);

    fclose(fp);
    ss_mpi_sys_munmap(y_virt, y_plane_size);
    ss_mpi_sys_munmap(uv_virt, uv_plane_size);

    printf("成功保存 YUV 文件: %s (分辨率:%dx%d)\n",
           filename, frame->width, frame->height);
    return 0;
}

void get_frame_sample(td_void *arg)
{
    int cnt = 1;
    sleep(2);

    ot_video_frame_info base_frm_info = {0};
    td_s32 ret = ss_mpi_vpss_get_chn_frame(0, 0, &base_frm_info, -1); // 假设获取帧

    if (ret == TD_SUCCESS)
    {
        printf("Frame信息: \n");
        printf("  分辨率: %dx%d\n", base_frm_info.video_frame.width, base_frm_info.video_frame.height);
        printf("  Y跨距: %d, UV跨距: %d\n",
               base_frm_info.video_frame.stride[0], base_frm_info.video_frame.stride[1]);
        printf("  Y物理地址: 0x%lx\n", base_frm_info.video_frame.phys_addr[0]);
        printf("  UV物理地址: 0x%lx\n", base_frm_info.video_frame.phys_addr[1]);

        if (save_video_frame_to_yuv(&base_frm_info.video_frame, "/tmp/output5.yuv") != 0)
        {
            fprintf(stderr, "保存失败\n");
        }

        sample_print("save file is ok \n");

        ss_mpi_vpss_release_chn_frame(0, 0, &base_frm_info);
    }
}

保存后的yuv数据,用yuvplayer打开,花屏,但是有原始图像纹理,是压缩模式OT_VIDEO_FORMAT_TILE_64x16的问题还是什么问题呢?

我来回答
回答5个
时间排序
认可量排序

UncleRoderick

41个粉丝

16

问答

3

专栏

16

资料

UncleRoderick 2025-03-20 13:40:23
认可0

改成OT_VIDEO_FORMAT_LINEAR试试

懒人精
懒人精   回复   UncleRoderick  2025-03-20 16:00:23
0

他这个和我的现象一样。

nowind
nowind   回复   懒人精  2025-03-20 16:06:59
0

我这

check_chn_return(ss_mpi_vdec_get_chn_param(i, &chn_param), i, “vdec get chn param”); // 获取解码通道参数。
if (sample_vdec[i].type == OT_PT_H264 || sample_vdec[i].type == OT_PT_H265 ||
sample_vdec[i].type == OT_PT_MP4VIDEO)
{
chn_param.video_param.dec_mode = sample_vdec[i].sample_vdec_video.dec_mode; // 解码模式:
chn_param.video_param.compress_mode = OT_COMPRESS_MODE_NONE; // 解码图像压缩模式
chn_param.video_param.video_format = OT_VIDEO_FORMAT_TILE_64x16; // 解码图像数据格式。
chn_param.video_param.out_order = OT_VIDEO_OUT_ORDER_DEC; // 解码图像输出顺序
}
设置的就是OT_COMPRESS_MODE_NONE,因为3519只支持这个,楼主提的改成OT_VIDEO_FORMAT_LINEAR,但是解码图像数据格式。详细描述请参考“系统控制”章节
Hi3519DV500仅支持OT_VIDEO_FORMAT_TILE_64x16。

UncleRoderick
UncleRoderick   回复   nowind  2025-03-20 17:32:37
0

建议改VPSS的,不是改VDEC的

展开 3 条评论

nowind

0个粉丝

1

问答

0

专栏

0

资料

nowind 2025-03-20 17:35:44
认可0

完结,mpp/tools/vpss_chn_dump.c,移植了一部分代码解决了。

或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
1、回答前请先确认你的回答是针对所回答的问题,并能帮助提问者解决问题的
2、拒绝“顶”“沙发”等毫无意义的灌水内容
3、不支持直接给源代码,建议提供解决问题的思路或指导
4、若想引用其他答主的答案,可使用“引用”功能,禁止直接复制,粘贴其他答主的答案
x
 

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区