背景

做视频编解码相关开发的过程中我们经常会遇到要把视频原始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. 跨域@RequestBody@RequestParam 和JSON.stringify

  2. 备忘:Linux内核编程的几个注意事项

    虚拟地址转物理地址要用__pa 内核程序创建的一段地址连续的共享内存,通过内存映射可以让用户态进程存取.之前在RHEL/CentOS的x86_64架构上工作正常.后来在aarch64架构的银河麒麟(L ...

  3. BUUCTF-[CISCN2019 华东南赛区]Web4

    BUUCTF-[CISCN2019 华东南赛区]Web4 看题 点击Read somethings,会跳转到 http://3fd8b1f9-614f-47ff-8e79-0f678e7bb4eb.n ...

  4. vue-父子组件之传值和单项数据流问题

    前言 我们知道 vue 中父子组件的核心概念是单项数据流问题,props 是单项传递的.那究竟什么是单项数据流问题,这篇文章来总结一下关于这个知识点的学习笔记. 正文 1.父组件传值给子组件 < ...

  5. 编程读写CAD文件验证

    背景 B/S应用系统,根据用户上传数据:业务数据和CAD坐标数据,经过一系列运筹算法运算后,输出一批坐标数据,作为给用户的规划结果.此时需要方便直观的给用户展示坐标数据.可选方式有两个: web页面画 ...

  6. vue的常见理论问题

    1.什么是 mvvm? mvvm 和 mvc 区别? MVVM 是 Model-View-ViewModel 的缩写.mvvm 是一种设计思想.Model 层代表数据模型,View 代表 UI 组件. ...

  7. Mysql 面试宝典

    实时更新 你用过哪些数据库? mysql redis mysql 和 redis 的区别? 比较点 Mysql Redis 数据库类型 关系型 非关系型 作用 持久化层 存储需要持久化的数据,数据存在 ...

  8. JS013. 重写toFixed( )方法,toFixed()原理 - 四舍五入?银行家舍入法?No!六舍七允许四舍五入√!

    以下为场景实测与原理分析,需要重写函数请直接滚动至页尾!!! 语法 - Number.prototype.toFixed( ) // toFixed()方法 使用定点表示法来格式化一个数值. numO ...

  9. js 点击复制文字

    复制input里面的文字 html: <input id="content" class="form-control" type="text&q ...

  10. mysql忘记root密码连接本地库

    http://www.cnblogs.com/zf2011/archive/2012/03/13/2393387.html 今天想做个小项目,决定用mysql数据库,但是好久没用mysql了,也忘掉了 ...