百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

ffmpeg学习笔记-初识ffmpeg(ffmpeg kux)

lipiwang 2024-11-15 22:02 12 浏览 0 评论

ffmpeg用来对音视频进行处理,那么在使用ffmpeg前就需要ffmpeg有一个大概的了解,这里使用雷神的ppt素材进行整理,以便于复习

音视频基础知识

视频播放器的原理

  • 播放视频的流程大致如下:
  • 常用播放器
    • 跨平台
      • VLC,Mplayer,ffplay等


    • Windows平台
      • 完美解码,终极解码,暴风影音

信息查看工具

综合信息查看:MediaInfo

二进制信息查看:UltraEdit

单项详细信息分析

封装格式:Elecard Format Analyzer

视频编码数据:Elecard Stream Eye

视频像素数据:YUV Player

音频采样数据:Adobe Audition

封装格式

封装格式的作用:视频码流和音频码流按照一定的格式存储在一个文件中
封装格式分析工具:
Elecard Format Analyzer

MPEG2-TS格式简介

不包含文件头。数据大小固定(188Byte)的TS Packet构成

FLV格式简介

包含文件头。数据由大小不固定的Tag构成

视频编码数据

  • 视频编码的作用:将视频像素数据(RGBYUV等)压缩成为视频码流,从而降低视频的数据量
  • 视频编码分析工具:Elecard Stream Eye

H.264格式简介

数据由大小不固定的NALU构成

最常见的情况下,1个NALU存储了1帧画面的压缩编码后的数据

H.264压缩方法
比较复杂。包含了帧内预测、帧间预测、熵编码、环路滤波等环节构成
可以将图像数据压缩100倍以上

相关学习资料推荐,点击下方链接免费报名,先码住不迷路~】

音视频免费学习地址:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

音频编码数据

音频编码的作用:将音频采样数据(PCM等)压缩成为音频码流,从而降低音频的数据量

AAC格式简介

数据由大小不固定的ADTS构成

AAC压缩方法
比较复杂
可以将音频数据压缩10倍以上

视频像素数据

视频像素数据作用:保存了屏幕上每个像素点的像素值


格式:

常见的像素数据格式有RGB24,RGB32,YUV420P,YUV422P,YUV444P等

压缩编码中一般使用的是YUV格式的像素数据,最为常见的格式为YUV420P

特点

频像素数据体积很大,一般情况下1小时高清视频的RGB24格式的数据体积为:

3600*25*1920*1080*3=559.9GByte

PS:这里假定帧率为25Hz,取样精度8bit

YUV格式像素数据查看工具:YUV Player

RGB格式简介

Red、Green、Blue三种颜色,可以混合成世界上所有的颜色

彩色图像中每个点,由R、G、B三个分量组成

以RGB24为例,图像像素数据的存储方式如下:

从图中可以看出,RGB24依次存储了每个像素点的R、G、B信息

PS:BMP文件中存储的就是RGB格式的像素数据

YUV格式简介

相关实验表明,人眼对亮度敏感而对色度不敏感。因而可以将亮度信息和色度信息分离,并对色度信息采用更“狠”一点的压缩方案,从而提高压缩效率

YUV格式中,Y只包含亮度信息,而UV只包含色度信息

以YUV420P为例,图像像素数据的存储方式如图所示

从图中可以看出,YUV420P首先存储了整张图像的Y信息,然后存储整张图像的U信息,最后存储了整张图像的V信息

音频采样数据

音频采样数据作用:保存了音频中每个采样点的值

特点

音频采样数据体积很大,一般情况下一首4分钟的PCM格式的歌曲体积为:

4*60*44100*2*2=42.3MByte

PS:这里假定采样率为44100Hz,采样精度为16bit

音频采样数据查看工具:Adobe Audition

PCM格式简介

单声道的情况下按照顺序存储每个采样点的数据

双声道的情况下按照“左右、左右”的顺序存储每个采样点两个声道的数据

在Windows下使用

背景

  • 使用广泛
    使用FFmpeg作为内核的视频播放器
    Mplayer,射手播放器,暴风影音,KMPlayer,QQ影音...
  • 使用FFmpeg作为内核的转码器
    格式工厂,狸窝视频转换器,暴风转码...

总而言之,FFmpeg是视频行业中的"瑞士军刀"

  • 特点
    基于命令行:FFmpeg界面不太人性化,操作相对复杂,但是也更加灵活
    开源:可以吸引全世界优秀的开发者加入其中进行开发

FFmpeg命令行工具的获取

下载地址

访问FFmpeg官网ffmpeg官网 → 选择Download → 选择 Windows Package → 进入Zeranoe FFmpeg网站

注意不要直接从FFmpeg官网下载源代码

版本说明

Zeranoe网站中的FFmpeg分为3个版本:

Static:只包含3个体积很大的exe

Shared:除了3个体积较小的exe之外,还包含了dll动态库文件

Dev:只包含了开发用的头文件(*.h)和导入库文件(*.lib)

PS: 命令行使用的时候下载Static或者Shared版本就可以了

使用

将下载下来的压缩包解压到任意目录(例如D:\ffmpeg)

打开命令行工具,切换到ffmpeg的bin文件夹

命令行中输入ffmpeg.exe,查看弹出的信息

ffmpeg.exe的使用

命令格式

功能 ffmpeg.exe用于视频的转码

最简单的命令 ffmpeg -i input.avi -b:v 640k output.ts

该命令将当前文件夹下的input.avi文件转换为output.ts文件,并将output.ts文件视频的码率设置为640kbps

命令格式

ffmpeg -i {输入文件路径} -b:v {输出视频码率} {输出文件路径}

所有的参数都是以键值对的形式指定的。例如输入文件参数是"-i",而参数值是文件路径;输出视频码率参数是"-b:v",而参数值是视频的码率值。但是注意位于最后面的输出文件路径前面不包含参数名称

命令参数

PS:详细的参数可以访问http://ffmpeg.org/ffmpeg.html

ffplay.exe的使用

命令格式

功能 ffplay.exe用于视频的播放

最简单的命令 ffplay input.avi

该命令将播放当前文件夹下的input.avi文件

命令格式

ffplay {输入文件路径}

ffplay.exe的参数格式和ffmpeg.exe是类似的。所有的参数都是以键值对的形式指定的(由于不包含输出文件,所以只能指定输入参数)。注意位于最后面的输入文件路径前面不包含参数名称

PS:详细的参数可以访问http://ffmpeg.org/ffplay.html

视频解码器

视频解码知识

纯净的视频解码流程

压缩编码数据 -> 像素数据

例如解码H.264,就是"H.264码流 -> YUV"

一般的视频解码流程

视频码流一般存储在一定的封装格式(例如MP4、AVI等)中。封装格式中通常还包含音频码流等内容

对于封装格式中的视频,需要先从封装格式中提取中视频码流,然后再进行解码

例如解码MKV格式的视频文件,就是"MKV -> H.264码流 -> YUV"

VC下FFmpeg开发环境的搭建

新建控制台工程

打开VC++

文件 -> 新建 -> 项目 -> Win32控制台应用程序


拷贝FFmpeg开发文件

头文件(*.h)拷贝至项目文件夹的include子文件夹下

导入库文件(*.lib)拷贝至项目文件夹的lib子文件夹下

动态库文件(*.dll)拷贝至项目文件夹下

PS:如果直接使用官网上下载的FFmpeg开发文件。则可能还需要将MinGW安装目录中的inttypes.h,stdint.h,_mingw.h三个文件拷贝至项目文件夹的include子文件夹下

配置开发文件

打开属性面板

解决方案资源管理器 -> 右键单击项目 -> 属性

头文件配置

配置属性 -> C/C++ -> 常规 -> 附加包含目录,输入"include"(刚才拷贝头文件的目录)

导入库配置

配置属性 -> 链接器 -> 常规 -> 附加库目录,输入"lib"(刚才拷贝库文 件的目录

配置属性 -> 链接器 -> 输入 -> 附加依赖项,输入"avcodec.lib; avformat.lib; avutil.lib; avdevice.lib; avfilter.lib; postproc.lib; swresample.lib; swscale.lib"(导入库的文件名)

动态库不用配置

测试
创建源代码文件
在工程中创建一个包含main()函数的C/C++文件(如果已经有了可以跳过这一步)
包含头文件
如果是C语言中使用FFmpeg,则直接使用下面代码

# include "libavcodec/avcodec.h"

如果是C++语言中使用FFmpeg,则使用下面代码

#define __STDC_CONSTANT_MACROS
extern "C"
{
    #include "libavcodec/avcodec.h"
}

main()中调用一个FFmpeg的接口函数

例如下面代码打印出了FFmpeg的配置信息

int main(int argc, char* argv [])
{
    printf("%s", avcodec_configuration());
    return 0;
}

如果运行无误,则代表FFmpeg已经配置完成

FFmpeg库简介 FFmpeg一共包含8个库

avcodec:编解码(最重要的库)

avformat:封装格式处理

avfilter:滤镜特效处理

avdevice:各种设备的输入输出

avutil:工具库(大部分库都需要这个库的支持)

postproc:后加工

swresample:音频采样数据格式转换

swscale:视频像素数据格式转换

FFmpeg解码的函数

FFmpeg解码的流程图如下所示

FFmpeg解码函数简介

av_register_all():注册所有组件

avformat_open_input():打开输入视频文件

avformat_find_stream_info():获取视频文件信息

avcodec_find_decoder():查找解码器

avcodec_open2():打开解码器

av_read_frame():从输入文件读取一帧压缩数据

avcodec_decode_video2():解码一帧压缩数据

avcodec_close():关闭解码器

avformat_close_input():关闭输入视频文件

FFmpeg解码的数据结构

  • FFmpeg解码的数据结构如下所示

FFmpeg数据结构简介

AVFormatContext:封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息

AVInputFormat:每种封装格式(例如FLV, MKV, MP4, AVI)对应一个该结构体

AVStream:视频文件中每个视频(音频)流对应一个该结构体

AVCodecContext:编码器上下文结构体,保存了视频(音频)编解码相关信息

AVCodec:每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体

AVPacket:存储一帧压缩编码数据

AVFrame:存储一帧解码后像素(采样)数据

FFmpeg数据结构分析

AVFormatContext

iformat:输入视频的AVInputFormat

nb_streams:输入视频的AVStream个数

streams:输入视频的AVStream []数组

duration:输入视频的时长(以微秒为单位)

bit_rate:输入视频的码率

AVInputFormat

name:封装格式名称

long_name:封装格式的长名称

extensions:封装格式的扩展名

id:封装格式ID

一些封装格式处理的接口函数

FFmpeg数据结构分析

AVStream

id:序号

codec:该流对应的AVCodecContext

time_base:该流的时基

r_frame_rate:该流的帧率

AVCodecContext

codec:编解码器的AVCodec

width, height:图像的宽高(只针对视频)

pix_fmt:像素格式(只针对视频)

sample_rate:采样率(只针对音频)

channels:声道数(只针对音频)

sample_fmt:采样格式(只针对音频)

AVCodec

name:编解码器名称

long_name:编解码器长名称

type:编解码器类型

id:编解码器ID

一些编解码的接口函数

FFmpeg数据结构分析

AVPacket

pts:显示时间戳

dts:解码时间戳

data:压缩编码数据

size:压缩编码数据大小

stream_index:所属的AVStream

AVFrame

data:解码后的图像像素数据(音频采样数据)

linesize:对视频来说是图像中一行像素的大小;对音频来说是整个音频帧的大小

width, height:图像的宽高(只针对视频)

key_frame:是否为关键帧(只针对视频)

pict_type:帧类型(只针对视频)。例如I,P,B

补充小知识

解码后的数据为什么要经过sws_scale()函数处理?

解码后YUV格式的视频像素数据保存在AVFrame的data[0]、data[1]、data[2]中。但是这些像素值并不是连续存储的,每行有效像素之后存储了一些无效像素。以亮度Y数据为例,data[0]中一共包含了linesize[0]*height个数据。但是出于优化等方面的考虑,linesize[0]实际上并不等于宽度width,而是一个比宽度大一些的值。因此需要使用sws_scale()进行转换。转换后去除了无效数据,width和linesize[0]取值相等

SDL显示

视频显示知识

  • 视频显示的流程
    视频显示的流程,就是将像素数据"画"在屏幕上的过程
    例如显示YUV,就是将YUV"画"在系统的窗口中

VC下SDL开发环境的搭建

新建控制台工程

打开VC++

文件 -> 新建 -> 项目 -> Win32控制台应用程序

拷贝SDL开发文件

头文件(*.h)拷贝至项目文件夹的include子文件夹下

导入库文件(*.lib)拷贝至项目文件夹的lib子文件夹下

动态库文件(*.dll)拷贝至项目文件夹下

配置开发文件

打开属性面板

解决方案资源管理器 -> 右键单击项目 -> 属性

头文件配置

配置属性 -> C/C++ -> 常规 -> 附加包含目录,输入"include"(刚才拷贝文件的目录)

导入库配置

配置属性 -> 链接器 -> 常规 -> 附加库目录,输入"lib"(刚才拷贝文件的目录)

配置属性 -> 链接器 -> 输入 -> 附加依赖项,输入"SDL2.lib; SDL2main.lib"(导入库的文件名)

动态库不用配置

测试

创建源代码文件

在工程中创建一个包含main()函数的C/C++文件(如果已经有了可以跳过这一步),后续步骤在该文件中编写源代码

包含头文件

如果是C语言中使用SDL,则直接使用下面代码

#include "SDL2/SDL.h"

如果是C++语言中使用SDL,则使用下面代码

extern "C"
{
    #include "SDL2/SDL.h"
}

main()中调用一个SDL的接口函数

例如下面代码初始化了SDL

int main(int argc, char* argv [])
{
    if(SDL_Init(SDL_INIT_VIDEO))
    {
        printf("Could not initialize SDL - %s\n", SDL_GetError());
    } else {
        printf("Success init SDL");
    }
    return 0;
}

如果运行无误,则代表SDL已经配置完成

SDL视频显示的函数

  • SDL视频显示的流程图如下所示

SDL视频显示函数简介

SDL_Init():初始化SDL系统

SDL_CreateWindow():创建窗口SDL_Window

SDL_CreateRenderer():创建渲染器SDL_Renderer

SDL_CreateTexture():创建纹理SDL_Texture

SDL_UpdateTexture():设置纹理的数据

SDL_RenderCopy():将纹理的数据拷贝给渲染器

SDL_RenderPresent():显示

SDL_Delay():工具函数,用于延时

SDL_Quit():退出SDL系统

SDL视频显示的数据结构

  • SDL视频显示的数据结构如下所示

SDL数据结构简介
SDL_Window:代表了一个"窗口"
SDL_Renderer:代表了一个"渲染器"
SDL_Texture:代表了一个"纹理"
SDL_Rect:一个简单的矩形结构

进阶-SDL中事件和多线程

SDL多线程

函数:SDL_CreateThread():创建一个线程

数据结构:SDL_Thread:线程的句柄

SDL事件

函数

SDL_WaitEvent()等待一个事件

SDL_PushEvent()发送一个事件

数据结构

SDL_Event:代表一个事件

fffmpeg + SDL视频播放器

FFmpeg和SDL整合实现视频播放器

  • 整合方式
    FFmpeg解码器实现了:
    视频文件 -> YUV
    SDL视频显示实现了:
    YUV -> 屏幕
    FFmpeg+SDL整合之后实现了:
    视频文件 -> YUV -> 屏幕

进阶:脱离开发环境的独立播放器

main()函数的参数

argc argv:全称为ARGument Counter和ARGument Vector。其中argv存储了来自于命令行的参数;而argc存储了参数的个数

例如在命令行中输入ffmpeg -i test.mkv test.ts,则argc取值为4,而argv[]数组取值如下:

argv [0] = "ffmpeg";
argv [1] = "-i";
argv [2] = "test.mkv";
argv [3] = "test.ts";

动态链接库(*.dll

动态链接库不能被编译进应用程序。因而使用应用程序的时候必须在相同目录下保存用到的动态链接库文件

MFC知识

  • 创建MFC工程的方法
    打开VC++
    文件 -> 新建 -> 项目 -> MFC应用程序
    应用程序类型 -> 基于对话框
    取消勾选"使用Unicode库"(暂不详细介绍)
  • 设置控件

找到"工具箱",就可以将相应的控件拖拽至应用程序对话框中

常用控件有:Button,Edit Control,Static Text等

找到"属性"选项卡

可以在"Caption"属性上修改控件上的文字

可以在"ID"属性上修改控件上的ID(ID是控件的标识,不可重复)

添加消息响应函数

双击Button控件,就可以给该控件添加消息响应函数

在菜单栏的"项目 -> 类向导"处,可以添加更多种类的消息响应函数

MFC最简单的弹出消息框的函数是AfxMessageBox("HelloWorld")

FFmpeg + SDL + MFC实现图形界面视频播放器

FFmpeg解码器与MFC的整合

需要将视频文件路径从MFC界面上的Edit Control控件传递给FFmpeg解码器

GetWindowText()

SDL与MFC的整合

需要将SDL显示的画面绘制到MFC的Picture Control控件上

SDL_CreateWindowFrom()

PS:SDL2有一个Bug。在系统退出的时候会把显示图像的控件隐藏起来,因此需要调用该控件的ShowWindow()方法将控件显示出来

原文 ffmpeg学习笔记-初识ffmpeg_cj5785的博客-CSDN博客

相关推荐

前端入门——css 网格轨道详细介绍

上篇前端入门——cssGrid网格基础知识整体大概介绍了cssgrid的基本概念及使用方法,本文将介绍创建网格容器时会发生什么?以及在网格容器上使用行、列属性如何定位元素。在本文中,将介绍:...

Islands Architecture(孤岛架构)在携程新版首页的实践

一、项目背景2022,携程PC版首页终于迎来了首次改版,完成了用户体验与技术栈的全面升级。作为与用户连接的重要入口,旧版PC首页已经陪伴携程走过了22年,承担着重要使命的同时,也遇到了很多问题:维护/...

HTML中script标签中的那些属性

HTML中的<script>标签详解在HTML中,<script>标签用于包含或引用JavaScript代码,是前端开发中不可或缺的一部分。通过合理使用<scrip...

CSS 中各种居中你真的玩明白了么

页面布局中最常见的需求就是元素或者文字居中了,但是根据场景的不同,居中也有简单到复杂各种不同的实现方式,本篇就带大家一起了解下,各种场景下,该如何使用CSS实现居中前言页面布局中最常见的需求就是元...

CSS样式更改——列表、表格和轮廓

上篇文章主要介绍了CSS样式更改篇中的字体设置Font&边框Border设置,这篇文章分享列表、表格和轮廓,一起来看看吧。1.列表List1).列表的类型<ulstyle='list-...

一文吃透 CSS Flex 布局

原文链接:一文吃透CSSFlex布局教学游戏这里有两个小游戏,可用来练习flex布局。塔防游戏送小青蛙回家Flexbox概述Flexbox布局也叫Flex布局,弹性盒子布局。它决定了...

css实现多行文本的展开收起

背景在我们写需求时可能会遇到类似于这样的多行文本展开与收起的场景:那么,如何通过纯css实现这样的效果呢?实现的难点(1)位于多行文本右下角的展开收起按钮。(2)展开和收起两种状态的切换。(3)文本...

css 垂直居中的几种实现方式

前言设计是带有主观色彩的,同样网页设计中的css一样让人摸不头脑。网上列举的实现方式一大把,或许在这里你都看到过,但既然来到这里我希望这篇能让你看有所收获,毕竟这也是前端面试的基础。实现方式备注:...

WordPress固定链接设置

WordPress设置里的最后一项就是固定链接设置,固定链接设置是决定WordPress文章及静态页面URL的重要步骤,从站点的SEO角度来讲也是。固定链接设置决定网站URL,当页面数少的时候,可以一...

面试发愁!吃透 20 道 CSS 核心题,大厂 Offer 轻松拿

前端小伙伴们,是不是一想到面试里的CSS布局题就发愁?写代码时布局总是对不齐,面试官追问兼容性就卡壳,想跳槽却总被“多列等高”“响应式布局”这些问题难住——别担心!从今天起,咱们每天拆解一...

3种CSS清除浮动的方法

今天这篇文章给大家介绍3种CSS清除浮动的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。首先,这里就不讲为什么我们要清楚浮动,反正不清除浮动事多多。下面我就讲3种常用清除浮动的...

2025 年 CSS 终于要支持强大的自定义函数了?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是CSS自定义属性CSS自...

css3属性(transform)的一个css3动画小应用

闲言碎语不多讲,咱们说说css3的transform属性:先上效果:效果说明:当鼠标移到a标签的时候,从右上角滑出二维码。实现方法:HTML代码如下:需要说明的一点是,a链接的跳转需要用javasc...

CSS基础知识(七)CSS背景

一、CSS背景属性1.背景颜色(background-color)属性值:transparent(透明的)或color(颜色)2.背景图片(background-image)属性值:none(没有)...

CSS 水平居中方式二

<divid="parent"><!--定义子级元素--><divid="child">居中布局</div>...

取消回复欢迎 发表评论: