关于ffmpeg解码输出的YUV转RGB花屏问题

2023-05-16

现象

最近尝试基于ffmpeg封装一个dll, 用于视频解码, 然后将yuv转成RGB, 用于在网页显示视频的画面.

可是我将YUV转成RGB之后, 发现花屏了. 

研究了很久, 计算方式没有发现问题, 代码如下.

yuv420pToRGB24(pFrame->data[0], pFrame->data[1], pFrame->data[2], 
       pFrame->width, pFrame->height, outputBuf);
void yuv420pToRGB24(const BYTE *yBuf, const BYTE *uBuf, const BYTE *vBuf,
    const int width, const int height,
    BYTE *rgbBuf) {
    int index = (width*height - 1) * 3;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            BYTE y = yBuf[i*width + j];
            BYTE u = uBuf[(i / 2)*(width / 2) + j / 2];
            BYTE v = vBuf[(i / 2)*(width / 2) + j / 2];

            int data = (int)(y + 1.772 * (u - 128));
            rgbBuf[index] = ((data < 0) ? 0 : (data > 255 ? 255 : data));

            data = (int)(y - 0.34414 * (u - 128) - 0.71414 * (v - 128));
            rgbBuf[index + 1] = ((data < 0) ? 0 : (data > 255 ? 255 : data));

            data = (int)(y + 1.402 * (v - 128));
            rgbBuf[index + 2] = ((data < 0) ? 0 : (data > 255 ? 255 : data));
            index -= 3;
        }
    }
}

调试分析

仔细看花屏的纹路, 是每行都偏一定的大小, 又由于观察到linesize[0]稍大于width (ffmpeg输出的linesize[0]会基于2的指数倍对齐), 

因此我怀疑是linesize[0], linesize[1], linesize[2] 对应的buf多出的部分参与了计算, 导致的问题. 

有可能每行都多出一小段, 造成出现上图中每行偏一点的情况.

为了验证这个猜测, 我尝试将做如下修改.

 

修改

将linesize[0]传入, 在每轮循环中, 遇到取yBuf, uBuf, vBuf时, 基于lineSize累加来计算地址偏移,

这样跳过无效的地址, 以下代码在计算中还可优化, 为了方便理解, 就保留成下面的样子.

花屏问题消失, 输出RGB保存为bmp显示出来了.

yuv420pToRGB24(pFrame->data[0], pFrame->data[1], pFrame->data[2], 
        pFrame->width, pFrame->height, pFrame->linesize[0], outputBuf);

void yuv420pToRGB24(const BYTE *yBuf, const BYTE *uBuf, const BYTE *vBuf,
    const int width, const int height, int lineSize,
    BYTE *rgbBuf) {
    int index = (width * height - 1) * 3;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            BYTE y = yBuf[i * lineSize + j];
            BYTE u = uBuf[(i / 2) * (lineSize / 2) + j / 2];
            BYTE v = vBuf[(i / 2) * (lineSize / 2) + j / 2];

            int data = (int)(y + 1.772 * (u - 128));
            rgbBuf[index] = ((data < 0) ? 0 : (data > 255 ? 255 : data));

            data = (int)(y - 0.34414 * (u - 128) - 0.71414 * (v - 128));
            rgbBuf[index + 1] = ((data < 0) ? 0 : (data > 255 ? 255 : data));

            data = (int)(y + 1.402 * (v - 128));
            rgbBuf[index + 2] = ((data < 0) ? 0 : (data > 255 ? 255 : data));
            index -= 3;
        }
    }
}

图像反了

虽然不花屏了, 但是转出来的RGB上下是颠倒的. 

所以再次修改代码, 将 ((height-i-1)*width + j)*3作为新的索引.

图像翻转回来, 这下彻底正常了. 

void yuv420pToRGB24(const BYTE *yBuf, const BYTE *uBuf, const BYTE *vBuf,
    const int width, const int height, int lineSize, BYTE *rgbBuf) {
    int dstIndex = 0;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            BYTE y = yBuf[i * lineSize + j];
            BYTE u = uBuf[(i / 2) * (lineSize / 2) + j / 2];
            BYTE v = vBuf[(i / 2) * (lineSize / 2) + j / 2];

            dstIndex = ((height - i - 1) * width + j) * 3;
            int data = (int)(y + 1.772 * (u - 128));
            rgbBuf[dstIndex] = ((data < 0) ? 0 : (data > 255 ? 255 : data));

            data = (int)(y - 0.34414 * (u - 128) - 0.71414 * (v - 128));
            rgbBuf[dstIndex + 1] = ((data < 0) ? 0 : (data > 255 ? 255 : data));

            data = (int)(y + 1.402 * (v - 128));
            rgbBuf[dstIndex + 2] = ((data < 0) ? 0 : (data > 255 ? 255 : data));
        }
    }
}

总结

如果不是观察到linesize[0]宽度稍大于width, 怎么也想不到这个跳过的方法.

所以, 在调试过程中遇到不合理的情况, 记下来, 方便在遇到问题时, 可以作为分析问题的依据.

 

代码

以下是我基于最新ffmpeg编译的代码, 包含转RGB, 存bmp文件.

https://github.com/gzx-miller/ffmpeg_simple_api

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于ffmpeg解码输出的YUV转RGB花屏问题 的相关文章

  • ffmpeg通过添加框或边框来扩展(而不是调整大小)视频大小

    假设我有一个特殊分辨率的视频 例如 1280x718 我想将其更改为 1280x720 但我宁愿只在顶部和底部添加一行 而不是将 718 像素垂直插值到 720 所以基本上 我正在寻找一种方法告诉 ffmpeg 创建 1280x720 的输
  • 使用 libx264 为 Raspberry pi 编译 Xuggler 时的问题 #2

    我正在尝试编译Xuggler http www xuggle com xuggler 对于 Raspberry Pi 在 Debian 操作系统上运行 又名 Raspbian 我遵循了可用的 基本构建说明 here http www xug
  • 访问 AVFrame 的每个像素

    我需要访问 FFMPEG 的 AVFrame 对象的每个像素信息 如果是 RGB 则每个像素的每种颜色 R G 和 B 我怎样才能做到这一点 如果您已经前进到正确的框架 类似于 img convert ctx ffmpeg sws getC
  • VLC 和 ffmpeg 如何协同工作?

    我从源代码编译了VLC 它运行良好 当我执行 Vlc 时 vlc 运行 我还从源代码编译了 ffmpeg 它也运行良好 当我执行 ffmpeg i f toto flv mp3 vn acodec copy new toto mp3 时 会
  • 如何计算位图的平均 RGB 颜色值

    在我的 C 3 5 应用程序中 我需要获取位图的红色 绿色和蓝色通道的平均颜色值 最好不使用外部库 这可以做到吗 如果是这样 怎么办 提前致谢 尝试让事情变得更精确 位图中的每个像素都有一定的 RGB 颜色值 我想获取图像中所有像素的平均
  • 如何将 mat 转换为 array2d

    我为dlib http dlib net face landmark detection ex cpp html那里的面部地标代码使用 array2d 来获取图像 但我喜欢使用 Mat 读取图像并转换为 array2d 因为 dlib 仅支
  • 重新采样 H264 视频以降低帧速率,同时保持高图像质量

    以下是感兴趣的视频的 mplayer 输出 br carina tmp mplayer foo mov mplayer Symbol ff codec bmp tags has different size in shared object
  • FFmpeg 不适用于 android 10,直接进入 onFailure(String message) 并显示空消息

    我在我的一个项目中使用 FFmpeg 进行视频压缩 在 Android 10 Google Pixel 3a 上 对于发送执行的任何命令 它会直接进入 onFailure String message 并显示空消息 所以我在我的应用程序 g
  • 使用 Ffmpeg 编辑视频元数据

    我想更改视频元数据 原始视频信息 ffmpeg i video mp4 Metadata major brand mp42 minor version 0 compatible brands isomavc1mp42 creation ti
  • ffmpeg concat:“不安全的文件名”

    尝试将一堆 mts 文件转换为一个大 mp4 文件 stephan rechenmonster mnt backupsystem archive2 Videos 20151222 PRIVATE AVCHD BDMV bin ffmpeg
  • 如何重置捕获像素的值

    我正在尝试创建一个 C 函数 该函数返回屏幕截图位图中每四个像素的 R G 和 B 值 这是我的代码的一部分 for int ix 4 ix lt 1366 ix ix 4 x x 4 for int iy 3 iy lt 768 iy i
  • Java - 红、绿、蓝获取RGB

    通过致电getRGB int x int y with a BufferedImage对象 得到一个负数 如何将三个不同的值 红色 绿色和蓝色 转换为这个单个负数 使用颜色类 new Color r g b getRGB
  • PHP HSV 到 RGB 公式理解

    我可以转换RGB价值观HSV使用以下代码 r r 255 g g 255 b b 255 h 0 s 0 v 0 min min min r g b max max max r g b r max min v max if r 0 h 0
  • 如何将 MP3 音频文件读入 numpy 数组/将 numpy 数组保存到 MP3?

    有没有办法从 MP3 音频文件中读取 写入 MP3 音频文件numpy具有类似 API 的数组scipy io wavfile read https docs scipy org doc scipy 0 14 0 reference gen
  • 计算热图颜色

    我正在制作一个由 HTML 表格组成的热图 该表包含n细胞并有一个lowest值和一个highest值 最高值始终高于最低值 每个细胞都有一个cell价值 所有这些值都是整数 具有最低值的单元格应为浅蓝色 缩放到具有最高值的单元格为深红色
  • 如何使用 ffmpeg 设置默认流

    我有一些 m4v 文件 我想用 ffmpeg 添加字幕 我知道我需要映射流以将它们放入输出文件中 但如何确保此字幕流将是默认流 字幕是 srt 人们似乎说它们与 mp4 容器不兼容 我需要先将字幕转换为什么 另外 各种流的顺序重要吗 视频流
  • Xuggler 未转换 .webm 文件?

    我只是尝试使用 Xuggler 将 mov 文件转换为 webm 这应该可以工作 因为 FFMPEG 支持 webm 文件 这是我的代码 IMediaReader reader ToolFactory makeReader home use
  • Python FFmpeg查询rtsp太慢

    目前 我正在尝试使用 python 和 FFmpeg 来查询原始格式为 h264 的 rtsp 数据 直播流视频的信息为 fps 29 分辨率 1280 720 我希望我可以以相同的格式 h264 查询数据并将其放入python队列中以便将
  • Android 中的 FFMpeg jni?

    我已经构建了 Bambuser http bambuser com opensource 提供的 FFMPEG 可执行文件和库 所以我设法构建了 Android 可执行文件和库 如何在 Eclipse 项目中链接这些库并从 Java 调用
  • C++ OpenCV 3.4 / FFMPEG 3.4.1 VideoWriter 和 MP4 输出文件格式

    我正在运行 Linux 内核 4 9 35 ti r44 的 ARM BeagleBone X 15 Debian 机器 在我的 C Qt 5 应用程序中 我想将 cv Mat 帧保存为 MP4 格式视频 我安装了 libx264 并从头开

随机推荐

  • 迭代器模式

    迭代器模式 标签 xff1a Java与设计模式 迭代器模式 提供一种方法顺序访问聚合对象 如List Set 内的每个元素 而又不暴露聚合对象的内部实现 图片来源 设计模式 可复用面向对象软件的基础 模式实现 Iterator amp A
  • 简洁的Java8

    简洁的Java8 Stream 标签 xff1a Java基础 再次回到阿里 感觉变化好大 一是服务资源Docker化 最牛逼的阿里DB团队竟然把DB放到了容器中 还放到了线上环境 二是全集团Java8 记得离开时还是1 6 1 5 甚至还
  • window远程桌面修改密码

    window远程桌面修改修改密码 windows服务器 xff0c 修改密码可以通过Ctrl 43 Alt 43 Del xff0c 调出修改密码的界面 xff0c 但是想要修改远程桌面连接windows服务器的密码 xff0c 通过Ctr
  • Expression #1 of ORDER BY clause is not in SELECT list,references column 'xxxxxxx'

    给数据库升了个级 xff0c 后台纷纷报错误 xff1a 报错信息 xff1a Expression 1 of ORDER BY clause is not in SELECT list references column 39 xxxx
  • Spring官网下载SpringFramework

    说明 太惨了 xff0c 我发现我的SpringFramework是5 1 1的 xff0c 然后我的JDK是1 7的 xff0c 好像是JDK版本太低所以不能使用 xff0c 所以我决定下载一个新的SpringFramework 刚好记录
  • windows驱动程序开发基础

    1 用户态驱动驱动程序和核心态驱动程序 下图描绘出了操作系统驱动程序的相关组成部分的概貌 xff1a Windows驱动程序既可以运行在用户态也可以运行在核心模态 l 用户态的驱动程序运行在非特权处理机模式 xff08 nonprivile
  • java语言如何求平方根

    package javaapplication1 64 author Administrator public class JavaApplication1 64 param args the command line arguments
  • Maven 3.5.2 导致 IDEA 下载依赖卡死失败

    Maven 3 5 2 导致 IDEA 下载依赖卡死失败 当 IDEA 使用 Maven 3 5 2 时 xff0c 新增依赖 xff0c 点击 Reload All Maven Projects xff0c 总是卡在 finished 上
  • ubuntu16.04如何正确安装python3.6.5?

    目录 1 下载python3 6 5源码 2 编译python3 6 5源码 3 创建新安装的python3链接 4 检查python3 6 5是否可以用终端输入 前言 安装环境 xff1a ubuntu16 04 64位 xff0c py
  • 总结几点 Wake On Lan (WOL) 失败的原因

    正文 在我想使用 Wake On Lan xff08 后文皆用 WOL 代替 xff09 这项技术远程开机时 xff0c 总是失败 xff0c 在查阅各种资料后成功使用上了 WOL xff0c 下面总结几点导致失败的原因 发送 Magic
  • ubuntu18.04开机进入命令行模式

    ubuntu18 04开机进入命令行模式 设置开机进入命令行模式 1 首先我们修改grub文件sudo vim etc default grub 用 注释掉GRUB CMDLINE LINUX DEFAULT 61 quiet xff0c
  • 十几次CATIA安装重装系统吐血问题总结

    十几次CATIA安装重装系统吐血问题总结 一 CATIA许可证问题 破解文件未放置在相应位置 xff1b 安装时未关闭杀毒软件 二 CATIA热键未启动 xff0c 点击确定退出 查找杀毒软件恢复区 xff0c 检查是否杀毒软件限制了CAT
  • shell里面if条件语句使用正则判断

    下面介绍的是shell脚本里面 xff0c if语句中的正则表达式语句结构 要想判断变量最后一位是否为数字可用 34 0 9 34 这个表达式 xff0c 在 里面不要双引号
  • 如果在linux上明明服务已经启动,外部浏览器还是访问不到页面要注意以下问题。

    一 防火墙的状态 有时打开防火墙外部不能访问 防火墙的命令 xff1a 查看防火墙状态 systemctl status firewalld 开启防火墙 systemctl start firewalld 关闭防火墙 systemctl s
  • appium中常见的几种点击方式

    首先从appium库里面导入webdriver xff0c 然后webdriver Remote 声明driver对象 想要使用TouchAction xff0c 必须要创建TouchAction对象 xff0c 通过对象调用想要执行的手势
  • appium里的滑动和拖拽,滑动解锁,手机滑动接电话。

    1 滑动和拖拽 我们在做自动化测试的时候 xff0c 有些按钮是需要滑动几次屏幕后才会出现 xff0c 此时 xff0c 我们需要使用代码来模拟手指的滑动 xff0c 也就是接下来要学的滑动和拖拽了 1 1 swipe滑动事件 从一个坐标位
  • Flutter中http请求抓包的解决方案

    这篇文章主要给大家介绍了关于Flutter中http请求抓包的完美解决方案 xff0c 文中通过示例代码介绍的非常详细 xff0c 对大家的学习或者使用Flutter具有一定的参考学习价值 前言 前阵子有同学反馈Flutter中的http请
  • CSRF 攻击的应对之道

    CSRF 攻击的应对之道 牛 刚 和 童 强国 2011 年 2 月 24 日发布 CSRF 背景与介绍 CSRF xff08 Cross Site Request Forgery 跨站域请求伪造 xff09 是一种网络的攻击方式 xff0
  • py文件打包成exe可执行文件

    pyinstaller打包工具 官网 xff1a https pypi org project PyInstaller 一 安装命令 xff1a pip3 install pyinstaller 二 打包命令 xff08 首先打开cmd命令
  • 关于ffmpeg解码输出的YUV转RGB花屏问题

    现象 最近尝试基于ffmpeg封装一个dll 用于视频解码 然后将yuv转成RGB 用于在网页显示视频的画面 可是我将YUV转成RGB之后 发现花屏了 研究了很久 计算方式没有发现问题 代码如下 yuv420pToRGB24 pFrame