[FFMpeg] 非标准分辨率视频Dump YUV注意事项
背景
做视频编解码相关开发的过程中我们经常会遇到要把视频原始YUV数据保存下来查看的情况。
使用FFMpeg对视频解码之后原始图片数据都是保存在AVFrame这一结构中,很多时候我们都按照图像的长宽来对数据进行保存,这在绝大部分标准分辨率中都是可行的,因为图像的宽度在内存中能刚好满足CPU的字节对齐。
而对于非标准分辨率的视频来说,应该注意AVFrame的linesize可能比实际的图像宽度要大。
如我在解码一个858x360分辨率的视频成YUV420P的时候,其解码出来的帧的linesize分别为{896,448,448},可以看到linesize[0]大于858,相关解释可以见AVFrame结构体定义的备注:
/**
* For video, size in bytes of each picture line.
* For audio, size in bytes of each plane.
*
* For audio, only linesize[0] may be set. For planar audio, each channel
* plane must be the same size.
*
* For video the linesizes should be multiples of the CPUs alignment
* preference, this is 16 or 32 for modern desktop CPUs. // <-- Suiyek: Ref Here
* Some code requires such alignment other code can be slower without
* correct alignment, for yet other it makes no difference.
*
* @note The linesize may be larger than the size of usable data -- there
* may be extra padding present for performance reasons.
*/
int linesize[AV_NUM_DATA_POINTERS];
不难看出,AVFrame.data的数据存放格式是这样的:
data[i]:
[ (width >> component-shift) data | padding data ]
|<- - linesize[i] - ->|
所以我们在dump YUV的时候不能仅仅使用宽高来计算数据大小,应该去掉linesize的对齐长度(以YUV420P为例):
void DumpYUV420P(const AVFrame* frame, const char* name) {
if (!frame->width || !frame->height)
return;
int ws, hs;
// 取得当前像素格式的U/V分量(若有)的右移系数(其实就是除以多少..)
av_pix_fmt_get_chroma_sub_sample(static_cast<AVPixelFormat>(frame->format), &ws, &hs);
int offset = 0;
std::ofstream ofs(name, std::ios::binary | std::ios::app);
for (int i = 0; i < frame->height; i++)
{
ofs.write((char*)(frame->data[0] + offset), frame->width);
offset += frame->linesize[0];
}
offset = 0;
for (int i = 0; i < frame->height >> hs; i++)
{
ofs.write((char*)(frame->data[1] + offset), frame->width >> ws);
offset += frame->linesize[1];
}
offset = 0;
for (int i = 0; i < frame->height >> hs; i++)
{
ofs.write((char*)(frame->data[2] + offset), frame->width >> ws);
offset += frame->linesize[2];
}
ofs.close();
}
参考
FFMpeg在很多地方都有做数据字节对齐的优化,字节对齐是很常见的计算机软件优化手段,可以参考:Data structure alignment
[FFMpeg] 非标准分辨率视频Dump YUV注意事项的更多相关文章
- Linux BSP非标准HDMI分辨率
Linux BSP非标准HDMI分辨率 Intrinsyc公司发布了它的一个新的Linux BSP软件的发布 打开-Q820 开发套件基于Linux内核版本.支持的软件功能包括HDMI输出,可以支持标 ...
- 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...
- 最简单的基于FFmpeg的libswscale的示例(YUV转RGB)
===================================================== 最简单的基于FFmpeg的libswscale的示例系列文章列表: 最简单的基于FFmpeg ...
- 最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))
===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...
- ffmpeg在asp.net 视频转换
ffmpeg是一个源于Linux的工具软件,是FLV视频转换器,可以轻易地实现FLV向其它格式avi.asf. mpeg的转换或者将其它格式转换为flv.在视频播客中,我们通常使用它把我们上传的视频转 ...
- 利用FFmpeg玩转Android视频录制与压缩(二)<转>
转载出处:http://blog.csdn.net/mabeijianxi/article/details/72983362 预热 时光荏苒,光阴如梭,离上一次吹牛逼已经过去了两三个月,身边很多人的女 ...
- 交叉编译多平台 FFmpeg 库并提取视频帧
原文地址: 交叉编译多平台 FFmpeg 库并提取视频帧 交叉编译多平台 FFmpeg 库并提取视频帧 本文档适用于 x86 平台编译 armeabi.armeabi-v7a.arm64-v8a.x8 ...
- 交叉编译多平台 FFmpeg 库并提取视频帧(转)
交叉编译多平台 FFmpeg 库并提取视频帧 转 https://www.cnblogs.com/leviatan/p/11142579.html 本文档适用于 x86 平台编译 armeabi.a ...
- ffmpeg最简单的解码保存YUV数据 <转>
video的raw data一般都是YUV420p的格式,简单的记录下这个格式的细节,如有不对希望大家能指出. YUV图像通常有两种格式,一种是packet 还有一种是planar 从字面上 ...
随机推荐
- [SWMM]汇水区特征宽度的计算方法
SWMM模型产流计算中,有一个比较重要的参数就是子汇水区的特征宽度(width),这个参数对地表汇流时间和峰值有一定的影响.子汇水区特征宽度的计算方法有很多,这里介绍比较常用的两种: (1)采用面积除 ...
- MZY项目笔记:session歧路
from my typora MZY项目笔记:session歧路 文章目录 MZY项目笔记:session歧路 那该怎么办? 1. 手动加上cookie的header. 2.自己模拟一个Session ...
- JFrame显示刷新
1 import java.awt.BorderLayout; 2 import java.awt.Font; 3 import java.awt.event.ActionEvent; 4 impor ...
- Git修改历史commit的author信息
前言 "嘀嗒嘀嗒",抬头看向墙上的钟表,此时已是凌晨1点.小明终于把Go语言圣经第二章的笔记写完,保存commit,提交,然后睡觉. 额,等等,不对,小明发现他用的是公司的git账 ...
- Linux从头学09:x86 处理器如何进行-层层的内存保护?
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- 4种Golang并发操作中常见的死锁情形
摘要:什么是死锁,在Go的协程里面死锁通常就是永久阻塞了,你拿着我的东西,要我先给你然后再给我,我拿着你的东西又让你先给我,不然就不给你.我俩都这么想,这事就解决不了了. 本文分享自华为云社区< ...
- 使用junit进行最简单的单元测试
使用junit进行最简单的单元测试 使用工具: jdk IDEA Maven 第一步 创建一个Maven项目 第二步 导入junit依赖 <dependency> <groupId& ...
- (五)羽夏看C语言——结构体与类
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
- Vuex的同步异步存值取值
1. vue中各个组件之间传值 1.父子组件 父组件-->子组件,通过子组件的自定义属性:props 子组件-->父组件,通过自定义事件:this.$emit('事件名',参数1,参数2, ...
- Docker容器编排工具——docker-compose
1.docker-compose介绍 2.使用的三个步骤 3.安装docker-compose yum install docker-compose 4.docker-compose.yml 文件 ( ...