Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mpi_dec_test解码之后的sp格式的yuv文件需要转rgb,接着播放视频 #755

Open
Hanln-77 opened this issue Jan 2, 2025 · 0 comments

Comments

@Hanln-77
Copy link

Hanln-77 commented Jan 2, 2025

1.想问一下,这个yuv转rgb的格式转换过程是不是可以用RGA
2.官方的rga库是airockchip/librga嘛
3.我看mpp代码里也有rga相关的内容,这是集成在一块儿了嘛
4.这个librga的库是不是一定要用c++工程会好一些,用c工程会出现符号明明在.a里面却某些函数编译不了 显示未定义
例如这里面的get_bpp_from_format函数就不行
int play_yuv420_rga(char *file, uint32_t width, uint32_t height)
{
struct modeset_output *iter;
struct modeset_buf *buf;
int j, k, off;
int ret;

IM_STATUS rga_status;
im_rect src_rect, dst_rect;
rga_buffer_t src_buf, dst_buf;

// 打开 YUV 文件
FILE *fp = fopen(file, "rb");
if (!fp) {
    perror("Failed to open YUV file");
    return -1;
}

// 计算 YUV420 帧大小
uint32_t frame_size = width * height * 3 / 2;

// 分配 YUV 数据缓冲区
char *yuv_data = (uint8_t *)malloc(frame_size);
if (!yuv_data) {
    perror("Failed to allocate memory for YUV frame");
    fclose(fp);
    return -1;
}

// 分配 RGB 数据缓冲区
char *rgb_data = (uint8_t *)malloc(width * height * 3);
if (!rgb_data) {
    perror("Failed to allocate memory for RGB frame");
    free(yuv_data);
    fclose(fp);
    return -1;
}

memset(&src_rect, 0, sizeof(src_rect));
memset(&dst_rect, 0, sizeof(dst_rect));
memset(&src_buf, 0, sizeof(src_buf));
memset(&dst_buf, 0, sizeof(dst_buf));
memset(rgb_data, 0, width*height*get_bpp_from_format(RK_FORMAT_RGB_888));

// 循环读取每一帧 YUV 数据并转换为 RGB
while (fread(yuv_data, 1, frame_size, fp) == frame_size) 
{
    // // 导入 YUV 数据到源缓冲区
    // src_img_handle = importbuffer_virtualaddr(yuv_data, width * height * get_bpp_from_format(RK_FORMAT_YCbCr_420_SP));
    // // 导入 RGB 数据到目标缓冲区
    // dst_img_handle = importbuffer_virtualaddr(rgb_data, width * height * get_bpp_from_format(RK_FORMAT_RGB_888));=

    // 包装缓冲区
    src_buf = wrapbuffer_handle(yuv_data, width, height, RK_FORMAT_YCbCr_420_SP);
    dst_buf = wrapbuffer_handle(rgb_data, width, height, RK_FORMAT_RGB_888);

    printf("src_buf.width = %d dst_buf.width = %d\n", src_buf, dst_buf);
    if(src_buf.width == 0 || dst_buf.width == 0) {
        printf("%s, %s\n", __FUNCTION__, imStrError());
        return -1;
    }

    src_buf.format = RK_FORMAT_YCbCr_420_SP;
    dst_buf.format = RK_FORMAT_RGB_888;
    
    ret = imcheck(src_buf, dst_buf, src_rect, dst_rect);
    if (IM_STATUS_NOERROR != ret) {
        printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
        return -1;
    }

    // 执行颜色空间转换(YUV420 转 RGB888)
    ret = imcvtcolor(src_buf, dst_buf, src_buf.format, dst_buf.format);
    if (ret != IM_STATUS_SUCCESS) {
        printf("imcvtcolor failed, %s\n", imStrError(ret));
        free(yuv_data);
        free(rgb_data);
        fclose(fp);
        return -1;
    }

    // // 将转换后的 RGB 数据写入显示缓冲区
    // memcpy(rgb_data, dst_buf.vir_addr, width * height * 3);

    // 更新显示的缓冲区
    for (iter = output_list; iter; iter = iter->next) {
        buf = &iter->bufs[iter->front_buf ^ 1];  // 切换到前缓冲区或后缓冲区

        // 将 RGB 数据写入显示缓冲区
        for (j = 0; j < height; j++) {
            for (k = 0; k < width; k++) {
                off = buf->stride * j + k * 4;  // 计算帧缓冲区偏移量
                // 获取 RGB 分量
                uint32_t color = (*(rgb_data + j * width * 3 + k * 3) << 16) |    
                                (*(rgb_data + j * width * 3 + k * 3 + 1) << 8) | 
                                (*(rgb_data + j * width * 3 + k * 3 + 2));       
                // 设置帧缓冲区的像素颜色
                *(uint32_t*)&iter->extra_map[off] = color;  
            }
        }
    }

    // 刷新屏幕
    img_refresh();

    // 切换前后缓冲区
    for (iter = output_list; iter; iter = iter->next) iter->front_buf ^= 1;

    // 控制帧率
    usleep(1000000 / 30);  // 假设帧率为 30fps
}

// 释放资源
free(yuv_data);  // 释放 YUV 数据内存
free(rgb_data);  // 释放 RGB 数据内存
fclose(fp);  // 关闭文件

printf("play_over\n");
return 0;  // 返回成功

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant