FFmpeg基础知识与概念

FFmpeg 介绍

ffmpeg 是一个很好的开源的多媒体库,它包括了编解码,格式转化,复用器,解复用器,数据流处理,过滤和播放大多数多媒体格式,既包括较老的格式也支持很新的格式,它具有高度的可移植性。ffmpeg 可以在各种环境下构建,运行。从 Linux , 到 Mac OS , windows ,Android 都可以适用。
ffmpeg提供了一套丰富的视音频解码库,和方便使用的工具。我们将学习编译 ffpemg ,使用它的库来转换视频文件,并结合 sdl 编写播放器,从中学习到编解码的知识。

ffmpeg 命令行工具

ffmpeg 工具是一个高效快速的命令行工具,进行视音频不同格式之间的转换,
ffmpeg可以读取任意数量的输入“文件”(可以是常规文件,管道,网络流,抓取设备等)读取,由 -i 选项指定,并写入任意数量的输出“文件” (由纯输出文件名指定,在命令行中发现的不能被解释为选项的任何东西被认为是输出文件名。)
每个输入或输出文件原则上可以包含任意数量的不同类型的流(视频/音频/字幕/附件/数据)。 流的数量或类型可以由容器格式规定。 选择哪些输入并输出到哪个要么自动完成,要么使用-map选项。

  • 将输出文件的视频比特率设置为64 kbit/s

    ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi

  • 强制输出文件的帧速率24帧:

    ffmpeg -i input.avi -r 24 output.avi

  • 强制输入文件的帧速率(仅对raw格式有效)为1帧和输出文件的帧速率为24帧的:

    ffmpeg -r 1 -i input.m2v -r 24 output.avi

ffmpeg 的转码流程:
( ffmpeg 调用 libavformat 库(包含 demuxers )来读取输入文件,并从中获取包含编码数据的数据包。 当有多个输入文件时,ffmpeg 尝试通过输入流上的时间戳来保持它们的同步。
编码分组后传递到解码器。 解码器可以通过滤波进一步处理的未压缩帧(原始视频/ PCM音频/ …)。 在过滤之后,帧被传递到编码器,编码它们并输出编码分组。 最后,它们被传递到复用器,复用器将编码的数据包写入输出文件。)

ffserver

ffserver 是用于音频和视频的流服务器。 它支持多种推送方式,从文件流传输或者实时流推送。 如果有足够大的推送存储空间,还可以查找每个实时流的位置。
ffserver 从一些实例接收预录制文件或 FFM 流作为输入,然后通过 RTP / RTSP / HTTP 将其流式传输。
对于每个推送,可以有不同格式的不同输出流,每个格式由配置文件中的 部分指定。
推送发布的网址如:

`http://ffserver_ip_address:http_port/feed_name`

其中 ffserver_ip_address 是安装 ffserver 的计算机的 IP 地址,http_port 是 HTTP 服务器的端口号(通过 HTTPPort 选项配置),feed_name 是配置文件中定义的相应订阅源的名称。
多个流可以连接到同一个推送上。

ffplay

ffplay 是一个使用 ffmpeg 库和 sdl 库的非常简单和便携的媒体播放器。 它主要用作各种 ffmpeg api 的测试平台。
每个流使用一些选项,例如比特率或编解码器。 流指定符用于精确地指定选项所属的流。流指定符是一个字符串,通常添加选项名称,并用冒号分隔。 例如。 -codec:a:1 ac3 包含a:1 流标识符,它匹配第二个音频流。 因此,它将为第二个音频流选择 ac3 编解码器。流指定符可以匹配多个流,以便将选项应用于所有流。 例如。 -b:128k 中的流说明符匹配所有音频流。空流说明符匹配所有流。 例如,-codec copy 或 -codec:copy 将复制所有流,而不重新编码。流标识符的可能形式是:
stream_index : 使用此索引匹配流。 例如。 -threads:1 4 将第二个流的线程计数设置为4。
stream_type[:stream_index]: stream_type 是以下之一:视频的’v’或’V’,音频的’a’,字幕的’s’,数据的’d’和 附件的’t’。 ‘v’匹配所有视频流,’V’仅匹配未附加图片。如果给出 stream_index,则它匹配此类型的流 stream_index。 否则,它匹配此类型的所有流。
p:program_id[:stream_index]:如果给出 stream_index,则它将流与程序中具有 id program_id 的数字 stream_index 匹配。 否则,它匹配程序中的所有流。
stream_id or i:stream_id : 通过流 id 匹配流(例如 MPEG-TS 容器中的 PID )。
m:key[:value] : 匹配具有指定值的元数据标记键的流。 如果未指定值,则将包含给定标记的流与任何值 进行匹配。匹配具有可用配置的流,必须定义编解码器,并且存在诸如视频尺寸或音频采 样率的基本信息。请注意,在ffmpeg中,通过元数据进行的匹配仅适用于输入文件。

ffprobe

ffprobe从多媒体流收集信息,并以人和机器可读的方式打印。
例如,它可以用于检查由多媒体流使用的容器的格式以及包含在其中的每个媒体流的格式和类型。
如果在输入中指定了文件名,ffprobe 将尝试打开并探测文件内容。如果文件无法打开或识别为多媒体文件,则返回正的退出代码。
ffprobe 可以用作独立应用或与文本过滤器组合,其可以执行更复杂的处理,例如,统计处理或绘图。
选项用于列出 ffprobe 支持的某些格式,或用于指定要显示的信息,以及用于设置 ffprobe 将如何显示它。
ffprobe 输出设计为可以通过文本过滤器轻松解析,并且由选定 writer(由 print_format 选项指定)定义的一个或多个部分组成。
存储在容器或流中的元数据标签被识别并打印在相应的 “FORMAT” ,“STREAM” 或 “PROGRAM_STREAM” 部分中。

ffmpeg 为开发者准备的库

libavutil

libavutil 库是一个实用程序库,以辅助多媒体编程。 它包含安全可移植字符串函数,随机数生成器,数据结构,附加数学函数,加密和多媒体相关功能。 它不是 libavcodec 和 libavformat 所需的代码的库。
这个库的目标是:

  • 模块化 它应该具有很少的相互依赖性和在 ./configure 期间禁用单个部件的可能性。
  • 小 源和对象都应该小。
  • 高效 它应该具有低CPU和内存使用。
  • 有用 它应该添加人们很需要的功能。

libavcodec

libavcodec 库提供通用编码/解码框架,并包含用于音频,视频和字幕流的多个解码器和编码器,以及多个比特流滤波器。
共享架构提供从比特流 i/o 到 dsp 优化的各种服务,并且使得它适合于实现健壮和快速的编解码器。

libavformat

libavformat 库为音频、视频和字幕流的复用和解复用(多路复用和解复用)提供了一个通用框架。 它包括多媒体容器格式的多个多路复用器和多路分解器。
它还支持几种输入和输出协议来访问媒体资源。

libavdevice

libavdevice 库提供了一个通用框架,用于从许多常见的多媒体输入/输出设备抓取和渲染,并支持多个输入和输出设备,包括 Video4Linux2,VfW,DShow和ALSA。

libavfilter

libavfilter 库提供了一个通用的音频/视频过滤框架,包含几个过滤器,源和接收器模块。

libswscale

libswscale 库执行高度优化的图像缩放和颜色空间和像素格式转换操作。
具体来说,此库执行以下转换:

  • 新调整:是更改视频大小的过程。 有几个重新调整选项和算法可用。 这通常是有损耗的过程。
  • 像素格式转换:是转换图像的图像格式和颜色空间的过程,例如从平面 YUV420P 到 RGB24 转换。 它还可以处理 packed 转换,即从 packed 布局(属于在同一缓冲器中交织的不同平面的所有像素)转换为平面布局(属于存储在专用缓冲器或“平面”中的相同平面的所有样本)的转换。

如果源和目标颜色空间不同,这通常是有损过程。

libswresample

libswresample 库执行高度优化的音频重采样,重新矩阵化和样本格式转换操作。
具体来说,此库执行以下转换:
重新采样:是改变音频速率的过程,例如从 44100Hz 的高采样率到 8000Hz 。从高到低采样率的音频转换是有损耗的过程。有几个重采样选项和算法可用。

  • 格式转换:是将采样类型(例如从16位有符号采样转换为无符号8位或浮点采样)的过程。当从 packed 布局(所有属于在相同缓冲器中交错的不同通道的样本)到平面布局(属于存储在专用缓冲器或“平面”中的相同通道的所有样本)时,它还处理 packed 转换。
  • 重新矩阵化:是改变通道布局的过程,例如从立体声到单声道。当输入通道不能映射到输出流时,该过程是有损的,因为它涉及不同的增益因子和混合。
    通过专用选项启用各种其他音频转换(例如拉伸和填充)。
    制作动画屏幕捕捉
    电影文件有几个部分组成,文件本身称为容器,容器的类型决定文件中信息的位置。 本节实验容器的示例是 avi 和quicktime。 接下来,我们需要处理很多流:例如通常有一个音频流和一个视频流。流中的数据元素被称为帧。 每个流由不同种类的编解码器编码。 编解码器定义实际数据如何被 COTED和 DECDODE — 因此名称 CODEC。 编解码器的示例是 DivX 和 MP3 。 然后从流中读取分组。 数据包是可以包含数据位的数据片段,这些数据被解码成我们最终可以为我们的应用程序处理的原始帧。 为了我们的目的,每个分组包含完整的帧,或者在音频的情况下多个帧。
    处理视频和音频流是非常容易的,属于基本层次:
  • 从文件中找到视频流
  • 从视频流中读取数据包
  • 如果不是一帧完整的数据就继续执行上一步
  • 对帧数据做一些处理
  • 然后循环执行以上操作,直到结束
  • 在本实验中我们将对帧数据做一些处理,比如将每一帧的图像转为 jpg或者bmp或者ppm等格式保存下来。

sdl 介绍

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前 SDL 多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。 SDL(第一版)使用 GNU 宽通用公共许可证为授权方式,意指动态链接(dynamic link)其库并不需要开放本身的源代码。因此诸如《雷神之锤4》等商业游戏也使用SDL来开发。而第二版的SDL则改用Zlib授权来授权。
虽然 SDL 时常被比较为‘跨平台的 DirectX ’,然而事实上 SDL 是定位成以精简的方式来完成基础的功能,它大幅度简化了控制图像、声音、输出入等工作所需撰写的代码。但更高级的绘图功能或是音效功能则需搭配 OpenGL 和 OpenAL 等 API 来达成。另外它本身也没有方便创建图形用户界面的函数。 SDL 在结构上是将不同操作系统的库再包装成相同的函数,例如 SDL 在 Windows 平台上其实是 DirectX 的再包装,旧版本包装的是 DirectX 5,SDL 1.2 则是 DirectX 7 。而在使用 X11 的平台上(包括 Linux ),SDL 则是与 Xlib 库沟通来输出图像。 虽然 SDL 本身是使用C语言写成,但是它几乎可以被所有的编程语言所使用,例如:C++、Perl、Python(借由pygame库)、Pascal等等,甚至是Euphoria、Pliant这类较不流行的编程语言也都可行。 SDL库分为 Video、Audio、CD-ROM、Joystick 和 Timer 等若干子系统,除此之外,还有一些单独的官方扩充函数库。这些库由官方网站提供,并包含在官方文档中,共同组成了SDL的“标准库”:

  • SDL_image 支持时下流行的图像格式:BMP、PPM、XPM、 PCX、GIF、JPEG、PNG、TGA。
  • SDL_mixer 更多的声音输出函数以及更多的声音格式支持。
  • SDL_net 网络支持。
  • SDL_ttf TrueType字体渲染支持。
  • SDL_rtf 简单的RTF渲染支持。

测试代码:

#include "SDL/SDL.h"
int main( int argc, char* args[] )
{
    //声明表面
    SDL_Surface* hello = NULL;
    SDL_Surface* screen = NULL;
     //启动SDL
    SDL_Init( SDL_INIT_EVERYTHING );

    //设置窗口
    screen = SDL_SetVideoMode( 480, 208, 32, SDL_SWSURFACE );

    //加载图像
    hello = SDL_LoadBMP( "hello.bmp" );
    //将图像应用到窗口上
    SDL_BlitSurface( hello, NULL, screen, NULL );

    //更新窗口
    SDL_Flip( screen );

    //暂停
    SDL_Delay( 5000 );
    //释放已加载的图像
    SDL_FreeSurface( hello );

    //退出SDL
    SDL_Quit();

    return 0;
}  

这里的 hello.bmp 可以从上一节课的图片中随意选择一张,用 ffmpeg 转码就好了,ffmpeg -i xxx.jpg hello.bmp
gcc -o test2.out test2.c sdl-config --cflags --libs
./test2.out

参考文档
https://blog.csdn.net/kyl282889543/article/details/96490778
https://github.com/laboratory-coding/FFmpeg-SDL-Videos-Play/wiki/基础知识


文章作者: YUV420.COM
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 YUV420.COM !
评论
 上一篇
Android端音频变声方案 Android端音频变声方案
Android 端音频变声方案音频变声实质上是通过调整 PCM 数据的音调、节拍等属性,实现听感上的变化。如果是 mp3、aac 等压缩音频,则需提前解码成 PCM 数据,Android 端可以通过 MediaExtractor 及 Med
2020-01-21
下一篇 
图像基础知识与概念 图像基础知识与概念
RGB 介绍光的三原色是红色、绿色和蓝色,三种光相加会成为白色光。这是由于人类有三种视锥细胞分别对红、绿和蓝光最敏感。 三原色光和绘画中的“三原色”不同。绘画时用三种颜色洋红色、黄色和青色以不同的比例配合,会产生许多种颜色。如果三种色料相加
2020-01-21
  目录