背景

做视频编解码相关开发的过程中我们经常会遇到要把视频原始YUV数据保存下来查看的情况。

使用FFMpeg对视频解码之后原始图片数据都是保存在AVFrame这一结构中,很多时候我们都按照图像的长宽来对数据进行保存,这在绝大部分标准分辨率中都是可行的,因为图像的宽度在内存中能刚好满足CPU的字节对齐。

而对于非标准分辨率的视频来说,应该注意AVFramelinesize可能比实际的图像宽度要大。

如我在解码一个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注意事项的更多相关文章

  1. Linux BSP非标准HDMI分辨率

    Linux BSP非标准HDMI分辨率 Intrinsyc公司发布了它的一个新的Linux BSP软件的发布 打开-Q820 开发套件基于Linux内核版本.支持的软件功能包括HDMI输出,可以支持标 ...

  2. 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

    目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...

  3. 最简单的基于FFmpeg的libswscale的示例(YUV转RGB)

    ===================================================== 最简单的基于FFmpeg的libswscale的示例系列文章列表: 最简单的基于FFmpeg ...

  4. 最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))

    ===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...

  5. ffmpeg在asp.net 视频转换

    ffmpeg是一个源于Linux的工具软件,是FLV视频转换器,可以轻易地实现FLV向其它格式avi.asf. mpeg的转换或者将其它格式转换为flv.在视频播客中,我们通常使用它把我们上传的视频转 ...

  6. 利用FFmpeg玩转Android视频录制与压缩(二)<转>

    转载出处:http://blog.csdn.net/mabeijianxi/article/details/72983362 预热 时光荏苒,光阴如梭,离上一次吹牛逼已经过去了两三个月,身边很多人的女 ...

  7. 交叉编译多平台 FFmpeg 库并提取视频帧

    原文地址: 交叉编译多平台 FFmpeg 库并提取视频帧 交叉编译多平台 FFmpeg 库并提取视频帧 本文档适用于 x86 平台编译 armeabi.armeabi-v7a.arm64-v8a.x8 ...

  8. 交叉编译多平台 FFmpeg 库并提取视频帧(转)

    交叉编译多平台 FFmpeg 库并提取视频帧 转  https://www.cnblogs.com/leviatan/p/11142579.html 本文档适用于 x86 平台编译 armeabi.a ...

  9. ffmpeg最简单的解码保存YUV数据 <转>

    video的raw data一般都是YUV420p的格式,简单的记录下这个格式的细节,如有不对希望大家能指出.   YUV图像通常有两种格式,一种是packet 还有一种是planar    从字面上 ...

随机推荐

  1. Android WorkManager 定时任务

    App有时可能需要定期运行某些工作.例如,可能要定期备份数据.上传信息到服务器,定期获取新的内容等等. 在app运行期间,我们使用Handler也可以完成定期的功能.在这里我们介绍WorkManage ...

  2. docker容器 如何精简镜像减小体积

    写在前面 我们在上篇<Docker容器 关于镜像构建的安全问题>一起学习了如何构建一个基于安全的镜像,这篇小作文我们会学习镜像构建的另一个关键性问题,为何别人打造的镜像只有10MB而我的有 ...

  3. Vue.JS快速上手(指令和实例方法)

    1.声明式渲染 首先,我们要知道Vue是声明式渲染,那啥是声明式渲染,我们只需要告诉程序我们想要什么结果,其他的交给程序来做.与声明式渲染相对的是命令式渲染,即命令我们的程序去做什么,程序就会跟着你的 ...

  4. 经典深度学习CNN总结 - LeNet、AlexNet、GoogLeNet、VGG、ResNet

    参考了: https://www.cnblogs.com/52machinelearning/p/5821591.html https://blog.csdn.net/qq_24695385/arti ...

  5. 面试官:如何实现LRU?你学会了吗?

    面试官:来了,老弟,LRU缓存实现一下? 我:直接LinkedHashMap就好了. 面试官:不要用现有的实现,自己实现一个. 我:..... 面试官:回去等消息吧.... 大家好,我是程序员学长,今 ...

  6. (1)RabbitMQ在Docker上安装

    1.简介 在来学习RabbitMQ时候,我觉得很有必要先把它的环境先搭建起来,这样后面的示例才能进行.因为之前自己手动在Linux服务器上搭建过Elasticsearch,当时踩过太多坑了,浪费太多时 ...

  7. 洛谷P2115 Sabotage G 题解

    题目 [USACO14MAR]Sabotage G 题解 本蒟蒻又来了,这道题可以用二分答案来解决.我们可以设答案最小平均产奶量为 \(x \ (x \in[1,10000])\) .然后二分搜索 \ ...

  8. 二、grep文本搜索工具

    grep命令作为Unix中用于文本搜索的神奇工具,能够接受正则表达式,生成各种格式的输出.除此外,它还有大量有趣的选项. # 搜索包含特定模式的文本行: [root@centos8 ~]#grep p ...

  9. Linux下scp命令

    1.scp 是 secure copy 的缩写, scp 是 linux 系统下基于 ssh 登陆进行安全的远程文件拷贝命令. 2.scp 是加密的,rcp 是不加密的,scp 是 rcp 的加强版. ...

  10. noip模拟题7

    目录 T1:匹配 T2:回家 思路 上代码: T3:寿司 基本思路: 上代码: T1:匹配 ##思路:   首先,这道题既可以用KMP,也可以用hash   先说KMP,首先要注意的一点是:KMP的n ...