音视频开发19 FFmpeg 视频解码- 将 h264 转化成 yuv

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

视频解码过程

视频解码过程如下图所示:
⼀般解出来的是420p

FFmpeg流程

这里的流程是和音频的解码过程一样的,不同的只有在存储YUV数据的时候的形式

存储YUV 数据

如果知道YUV 数据的格式

前提:这里我们打开的h264文件,默认是YUV420P 格式的,

我们可以通过  AVFrame->frame 获得,获得的值如果是视频就 是 AVPixelFormat。

我们可以通过 AVPixelFormat ,知道该视频的编码是啥?

在正常情况下,我们需要判断AVPixelFormat是那种类型,当前代码中并没有判断是因为我们默认使用的YUV420P,那么怎么存储这个YUV420P呢?

首先我们这里要明白,一个AVFrame就是一张图片,假设AVframe 我们存储的是322 * 356 ,322并不是16的整倍数,322/16 = 20......2 也就是说一行会有2个字节的剩余
那么这个剩余的2个字节,怎么办呢?会多给14个字节和剩余的2个字节 结合起来。
因此如果我们用和音频类似的写法: fwrite(frame->data[0], 1, frame->width * frame->height,  outfile) 去写,就会有问题,因为要保证这里 width是16的整倍数
这时候就要用到 ffmpeg 的AVFrame给我们提供的 linesize[x]了,

核心代码

        // 一般H264默认为 AV_PIX_FMT_YUV420P, 具体怎么强制转为 AV_PIX_FMT_YUV420P 在音视频合成输出的时候讲解
        // frame->linesize[1]  因为有字节对齐的问题。
        // 这里先回顾一下 音频的处理方式,在交错模式的时候,使用的 声道数*每个声道有多少个音频样本 * 每个样本占用多少个字节,这是因为音频上 没有字节对齐的问题
        //字节对齐问题的根本是因为 ,对于一张 322 * 356 的图片来说 ,322并不是16的整倍数,322/16 = 20......2 也就是说一行会有2个字节的剩余
        //那么这个剩余的2个字节,怎么办呢?会多给14个字节和剩余的2个字节 结合起来。
        //因此如果我们用和音频类似的写法: fwrite(frame->data[0], 1, frame->width * frame->height,  outfile) 去写,就会有问题,因为要保证这里 width是16的整倍数
        //这时候就要用到 ffmpeg 的AVFrame给我们提供的 linesize[x]了,

//        uint8_t *data[AV_NUM_DATA_POINTERS]:
//        指向实际的帧数据的指针数组。
//        对于视频帧,这通常是图像平面(如YUV中的Y、U、V平面)。
//        对于音频帧,这通常是音频通道的数据指针。

//        int linesize[AV_NUM_DATA_POINTERS]:
//        每一行(视频)或每一个音频通道(音频)的大小。
//        对于视频,这通常是图像宽度的字节数。如果图像的宽度 除以 16 有余数,则这个值会凑成16的倍数。
//        对于音频,这通常是这个通道的字节数大小。 在交错模式下: 理论上等于   声道数 * 每个声道有多少个音频样本 * 每个样本占用多少个字节
//                            但是,测试发现,在第一个AVFrame包和最后一个 AVframe的时候,linesize[0]的值 比 声道数 * 每个声道有多少个音频样本 * 每个样本占用多少个字节 大于64.

        //了解了linesize[]的意义,对于一个avframe,就是包含了一帧,就是一张图片,
        //YUV420P的存储方式是这样的  YYYYYYYYUUVV
//        那么对于 一张 YUV420P (322 * 120)的图片来看,有多少个Y 呢?多少个U,多少个V呢?
//        Y的个数为:有 120行,一行一行的存储,每一行的实际大小为322, 但是存储322个Y后,就结束了吗?没有 ,因为有字节对齐问题,因此每次存储完322后,还要跳过14个字节,也就是实际大小为linesize[0],
        //我们先将Y全部存储完毕。
        //再存储U,U的个数是多少呢?这里要回头看一下YUV420P存储结构图,这里只是结论:宽高均是Y的一半,因此这里要注意存储U的写法
        //V的存储和U是一样的。
        // 正确写法  linesize[]代表每行的字节数量,所以每行的偏移是linesize[],但是真正存储的值 Y 是宽度,
        for(int j=0; j<frame->height; j++)
            fwrite(frame->data[0] + j * frame->linesize[0], 1, frame->width, outfile);
        for(int j=0; j<frame->height/2; j++)
            fwrite(frame->data[1] + j * frame->linesize[1], 1, frame->width/2, outfile);
        for(int j=0; j<frame->height/2; j++)
            fwrite(frame->data[2] + j * frame->linesize[2], 1, frame->width/2, outfile);

        // 错误写法 用source.200kbps.766x322_10s.h264测试时可以看出该种方法是错误的
        //  写入y分量
//        fwrite(frame->data[0], 1, frame->width * frame->height,  outfile);//Y
//        // 写入u分量
//        fwrite(frame->data[1], 1, (frame->width) *(frame->height)/4,outfile);//U:宽高均是Y的一半
//        //  写入v分量
//        fwrite(frame->data[2], 1, (frame->width) *(frame->height)/4,outfile);//V:宽高均是Y的一半

ffmpeg H264YUV420p 比较形象的说法就是把长长的一段连续的数据“切割”成一段段的数据。av_parser_parse2():解析获得一个Packet。av_parser_init(): 初始化AVCodecParserContext。使用的H264文件是D:/videos/264.dat(dat后缀名无所谓)方法二不需要查找流的信息,直接读取二进制文件,自己设置解码器ID。方法二:主要函数:av_parser_parse2()方法一:主要函数:av_read_frame()主要函数:av_read_frame() 阅读详情

相关推荐

H264YUV,循环获取每一帧数据

使用ffmpeg解码h264视频, 并获得每一帧数据

weixin_45331269的博客 946

音视频:将h264裸流YUV

本文旨在将h264裸流数据yuv数据,分为两种情况一种是读取h264文件,一次性将读取到的所有h264数据给到解码yuv,一种是从网络中接收含h264数据的RTP,这种情况下需要先对RTP包进行解包提取出h264数据,然后判断接收到一个完整的帧数据后再交给解码yuv。最后生成的yuv文件可以使用ffmpeg正常播放。对RTP包进行解包提取出h264数据的方法在前一篇文章中分析过,这里不在赘述。

qq_40709487的博客 1714

ffmpeg中,网络视频h264为什么默认的YUV而不是其他格式

也被称为AVC(高级视频编码),是一种视频压缩标准。这是一种高效的视频编码方法,可以在保持高质量的同时,大幅度减少所需的带宽和存储空间。H264编码的视频可以在各种设备上播放,包括电视、电脑、智能手机等。在视频处理中,H264用于压缩视频数据,使其更便于传输和存储。这是一种颜色编码系统,常用于视频系统。YUV模型定义了一个颜色空间,其中Y表示亮度(灰度),而U和V表示色度(色彩和饱和度)。这种颜色编码方式的优点是可以更有效地压缩颜色信息,因为人眼对亮度的敏感度远高于色度。

haleycat的博客 2168

h264解码保存为yuv格式

h264解码保存为yuv格式 使用ffmpeg库从摄像头读取h264数据进行解码和显示,最后保存为yuv格式的文件,开发环境为QTCreater。程序流程图如下图所示: ffmpeg.h头文件如下: #ifndef FFMPEG_H #define FFMPEG_H #include <QMainWindow> #include <QMutex> #include &l...

weixin_42538789的博客 2997

音视频开发—使用FFmpeg从纯H264码流中提取图片 C语言实现

本文讲述了如何通过FFmpegH264纯码流文件中提取出图片的详细操作和相关的代码

weixin_46999174的博客 2317

视频 YUV 格式编码成 H264

首先开始的时候我们插入一张雷神大大的图帮助大家理解一下我们今天的操作究竟属于那一步。 音视频格式封装层次 从上图可以看出我们要做的,就是将像素层的 YUV 格式,编码出编码层的 h264数据。 前面讲到我们已经成功编译出 iOS 中可用的 ffmpeg 的库了,那么我们首先熟悉一下今天我们要用到的 ffmpeg 中的函数和结构体 AVFormatContext: 数据文件操

ZH952016281的博客 2万+

一步步教ffmpeg的C语言音视频编程

前言 本文以 ffmpeg 工具,讲述如何认识音视频编程,你可以了解到常见视频格式的大概样子,一步步学会如何使用 ffmpeg 的 C 语言 API 本文重于动手实践,代码仓库:mpegUtil 笔者的开发环境:Arch Linux 4.19.12, ffmpeg version n4.1 解码过程总览 以下是解码流程图,逆向即是编码流程 本文是音视频编程入门篇,先略过传输协议层,主要讲格式层与...

lightfish_zhang的博客 1万+

音视频开发30 FFmpeg 视频编码- 流程以及重要API,H264编码原理说明,该章节使用h264编码说明

我们在前面已经编码完成的图像中,循环遍历每一个 块,将它作为预测块,用当前的编码块与这个块做差值,得到残差块,取残差块中 像素值的绝对值加起来最小的块为预测块,预测块所在的已经编码的图像称为参考 帧。得到的结果就是量化后的 系数。一般就是即将编码块的左边块、上边块、左上角块和右上角块, 通过将这些块与编码块相邻的像素经过多种不同的算法得到多个不同的预测 块。解码的时候,需要将 QStep 乘以量化后的系数得到变换系数,很明显这个变换系数和原始没有量 化的变换系数是不一样的,这个就是常说的有损编码。

hunandede的博客 1786

ffmpeg入门教程之YUV编码成h264 API详解

本文示例基于官方版本ffmpeg-20190926-87ddf9f-win64-dev编写 将YUV视频序列文件编码成H264文件 RGB YUV YUV存储格式 如何获取YUV图像序列文件 mp4--->h264(ffmpeg命令行) h264--->yuv(ffmpeg命令行) FFmpeg编码流程 fopen() 初始化AVFormatContext 创建AVStream 获取AVCodec 配置AVCodecContext YUV420P AVRational time_base 打开编码器 avc

奋斗的IT青年 5668

FFmepeg:从摄像头获取RTSP(h264、h265)视频流,解码YUV并保存成文件

ffmpegFFmpeg的名称来自MPEG视频编码标准,前面的“FF”代表“Fast Forward,是一套可以用来记录、换数字音频、视频,并能将其化为流的开源计算机程序。 平时我们下载的电影的文件的后缀(avi,mkv,rmvb等)就是所谓的封装方式,解封装就是将这些封装格式为压缩的视频数据(h264)和压缩音频数据(aac),解码就是把压缩的视频数据(h264)和压缩音频数据(aac...

weixin_42432281的博客 1万+

音视频H264/H256编码相关原理

我们播放的视频文件一般都是用一种封装格式封装起来的,封装格式的作用是什么呢?一般视频文件里不光有视频,还有音频,封装格式的作用就是把视频和音频打包起来。所以我们先要解封装格式,看有哪些视频流和哪些音频流,此时的音频流和视频流都还是压缩数据,不能直接用于显示的,这就需要解码。如FFmpeg 视频文件就是一个容器 (视频流(H264) 音频流(aac))。

wangyongyao1989的博客 5844

FFmpegH264解码实战

本文的内容是解码裸流,即从本地读取h264码流,然后解码YUV像素数据的过程。

yinshipin007的博客 1803

音视频流媒体高级开发FFmpeg6.0/WebRTC/RTMP/RTSP/编码解码

开源方案简介(视频 |12分钟23秒)AppRTC服务器组成(视频 |04分钟38秒)准备工作(视频 |02分钟37秒)AppRTC必要软件安装(1)(视频 |21分钟12秒)AppRTC必要软件安装(2)(视频 |14分钟03秒)1coturncolliderapprtc(视频 |19分钟19秒)nginx代理和运行测试(视频 |11分钟08秒)解决跨域问题和总结(视频 |17分钟42秒)课程展望(视频 |09分钟10秒)

C/C++Linux、音视频、DPDK 2112

FFmpeg QT 实现h264、h265 音视频播放(Native方式)

前言 FFmpeg 3.0 以后统一了音视频的编码方式,原有的API已经标记为弃用 或者已经被删除 测试环境: FFmpeg 4.0 Qt 5.12 Ubuntu 18.04 音视频格式 封装格式 常见的视频格式有AVI、MPEG、QuickTime、Flash、Mpeg-4、MKV、WebM,不同的格式有不同的特点 AVI: AVI视频格式,文件名以“.avi”结尾。AVI是英文Audio Video Interleave的缩写,该格式由微软开发。在所有Windows系统都能运行这种格式 MPEG

雨中人的专栏 6100

5G时代很火的音视频高级开发学习路线及知识点总结

我们先假设某人在音视频方面是零基础,也没学过任何数字信号处理相关知识,数学基础基本是高中水准,但是熟悉 C/C++ 开发,至少熟悉某一个平台下的编译调试IDE。 着重研究两个开源项目 ffmpeg 和 webRTC,主要看ffmpeg视频部分和webRTC的音频部分。 首先,从视频解码入手,这个最简单,调用 ffmpeg视频解码的基本代码只有100行左右,视频解码只要搞懂h.264就好了,80%+场景都是这个编码格式了,了解基本的 H.264 的 sps pps NAL等文件格式概念,了解YUV图像格式原

Linuxhus的博客 3244

FFmpeg解码H264视频裸流(直接可用)

1、写在前面此文章主要包含解码H264视频流数据,主要有以下几点:1、H264视频帧为Annex B格式,若使用AVCC格式可自行研究;2、H264视频裸流,非解码视频文件(若有需要我后期可添加这部分代码);3、支持输出RGB24或YUV420格式,其他可自行修改;4、FFmpeg官网代码迭代及接口变更较大,代码适应于FFmpeg3.4.2"Cantor"、3.3.7"Hilbert"等版本,较旧接口请看旧版本代码;

yinshipin007的博客 2541

音视频开发】第三章 FFmpeg 命令实战

保留编码格式:ffmpeg -i test.mp4 -vcodec copy -an test_copy.h264。强制格式:ffmpeg -i test.mp4 -acodec libmp3lame -vn test.mp3。强制格式:ffmpeg -i test.mp4 -vcodec libx264 -an test.h264。保留编码格式:ffmpeg -i test.mp4 -acodec copy -vn test.aac。禁用视频:ffplay test.mp4 -vn。

2022年毕业的萌新程序猿,输出一下自己的学习内容~ 1406

使用FFMPEG降低YUV视频分辨率(下采样)及FFMPEG相关操作详解

由于最近要将yuv视频下采样,于是使用ffmpeg快速将yuv视频下降分辨率。在此记录ffmpeg的基础使用方法和所遇到的问题: 1、下载FFmpeg 可到官网下载:https://www.ffmpeg.org/ 在这推荐一篇博客:https://www.cnblogs.com/liusx0303/p/7572050.html 里面详细的介绍了安装流程。 2、分辨率下降操作 操作方法一:下...

JonyeLH的博客 6662

音视频FFmpeg 硬件(AMD)解码H264

硬件编解码是利用GPU等独立硬件模块进行视频解码的技术,能降低CPU负荷,提高性能,但兼容性和画质处理较弱。软件编解码则完全依赖CPU,兼容性更好但功耗较高。常见的GPU编解码方案包括厂商SDK(如NVIDIA的NVENC、AMD的AMF)和FFmpeg集成方案。不同平台对硬件编解码的支持差异较大,Windows主要使用Direct3D/DXVA2,Linux支持VAAPI/VDPAU,而macOS使用VideoToolbox。FFmpeg提供了跨平台的硬件加速接口,但在功能完整性和易用性上仍有不足。硬件

Antonio915的博客 3204
上一篇: 音视频开发18 FFmpeg AVCodec 说明,AVCodecContext 说明
下一篇: 音视频开发20 FFmpeg 视频解码- MP4文件格式分析
hunandede
博客等级 码龄19年 2450粉丝 403原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值