本人希望打算深入研究音视频领域,音视频领域的内容很多,我自己打算从几方面循序渐进:FFmpeg常用功能实践, FFmpeg源码研究, OpenGL
, OpenGLES
, Metal
, AR
, WebRTC
, 直播架构等方向去研究。
音视频目前主要有哪些应用场景呢?
从上面这么多应用场景,我们可以看出音视频技术是多么重要,特别是5G时代,网络传输问题大大提升,更多的音视频需求会爆发出来。
我们可以看一下一个简单播放器的架构,如下图:
音频解码,视频解码一般都用FFmpeg解码,在IOS8 之后提供了VideoToolBox框架支持硬解码。
而视频渲染一般使用OpenGL直接用GPU渲染,视频渲染第三方框架有GPUImage, SDL, VLC
音频视频播放涉及到音视频同步是一个 复杂的技术。
学习一个技术,需要一个高效的方法,只有不断的实践才能理解深刻。学习FFmpeg我们也需要好的文档来学习,下面列举一些必备的学习文档地址:
上述都是英文的文档,如果英文学习困难,可以参考下面的中文资料:
此外推荐两本非常好的书籍:
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL
或GPL
许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec
,为了保证高可移植性和编解码质量,libavcodec
里很多code
都是从头开发的。
FFmpeg在Linux
平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows
、Mac OS X
等。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer
项目,而且当前FFmpeg也是放在MPlayer
项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"
法布里斯*贝拉:
- 高中就读期间开发了著名的可执行压缩程序LZEXE
- 2000年创建了FFmpeg项目
- 2011年,他用JavaScript写了一个Linux虚拟机(JSLinux)
- 他还是QEMU,TinyCC 的作者
2004年,迈克尔(Michael Niedermayer)接管FFmpeg, 迈克尔将滤镜子系统libavfilter
加入FFmepg项目中,使得FFmpeg的多媒体处理更加多样,更加方便。在FFmpeg发布了0.5版本后,很长一段时间没有进行新版本的发布,直到后来FFmpeg采用Git作为版本控制服务器以后才开始继续更新发布版本。
2011年3月, 由于FFmpeg项目中有一些提交者对FFmpeg的项目管理方式和发展方向不一致,FFmpeg团队分成了两派,其中一派认为FFmpeg应该更加专注于音视频开发,研究更新先进的音视频技术,这些人重新创建了一个新的项目叫Libav
。 另外一派认为他们要兼顾老的FFmpeg技术,然后逐步发展。
2015年8月迈克尔主动辞去FFmpeg项目负责人的职务。迈克尔从Libav中移植了大量的代码和功能到FFmpegZhong , 从此Libav又和FFmpeg合并一起发展。
USB
摄像头的图像,还可以进行屏幕录制,同时还支持以RTP
方式将视频流传送给支持RTSP
的流媒体服务器,支持直播应用。
- 在Linux平台上,
ffmpeg
对V4L2
的视频设备提供了很好的支持,如:./ffmpeg -t 10 -f video4linux2 -s 176*144 -r 8 -i /dev/video0 -vcodec h263 -f rtp rtp://192.168.1.105:5060 > /tmp/ffmpeg.sdp
以上命令表示:采集10秒钟视频,对video4linux2视频设备进行采集,采集QCIF(176*144)的视频,每秒8帧,视频设备为/dev/video0,视频编码为H263,输出格式为RTP,后面定义了IP地址及端口,将该码流所对应的SDP文件重定向到/tmp/ffmpeg.sdp中,将此SDP文件上传到流媒体服务器就可以实现直播了。- 在windows下关于ffmpeg视频采集的资料非常少,但是ffmpeg还是支持windows下视频采集的。ffmpeg支持windows下video for windows(VFW)设备的视频采集,不过
VFW
设备已经过时,正在被WDM
的视频设备所取代,但是ffmpeg还没有支持WDM的计划,不过好像有将WDM转为VFW的工具,因此ffmpeg还是可以在windows下进行视频采集的。
- ffmpeg视频转换功能。视频格式转换,比如可以将多种视频格式转换为flv格式,可不是视频信号转换 。
- ffmpeg可以轻易地实现多种视频格式之间的相互转换(
wma
,rm
,avi
,mod
等),例如可以将摄录下的视频avi
等转成视频网站所采用的flv
格式。
- 对于选定的视频,截取指定时间的缩略图。视频抓图,获取静态图和动态图,不提倡抓
gif
文件;因为抓出的gif
文件大而播放不流畅。- 给视频加水印功能
- 使用ffmpeg 视频添加水印(
logo
)。
我们先看一下一张FFmpeg的架构图:
AVFormat
中实现了目前多媒体领域中的绝大多数媒体封装格式,包括封装和解封装,如MP4
, FLV
, KV
, TS
等文件封装格式, RTMP
, RTSP
, MMS
, HLS
等网络协议封装格式。FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行媒体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块。
AVCodec中实现了目前多媒体绝大多数的编解码格式,既支持编码,也支持解码。
AVCodec除了支持MPEG4,AAC, MJPEG等自带的媒体编解码格式之外,还支持第三方的编解码器,如H.264(AVC)编码,需要使用x264编码器; H.265(HEVC)编码,需要使用x265编码器; MP3(mp3lame)编码,需要使用libmp3lame编码器。如果希望增加自己的编码格式,或者硬件编解码,则需要在AVCodec中增加相应的编解码模块。
git clone https://gitfmpeg.org/ffmpeg.git
从上面的帮助,我们可以尝试输入:./configure --list-decoders
查看所有解码器
aac dst mp1 s302m
aac_at dvaudio mp1_at sami
aac_fixed dvbsub mp1float sanm
aac_latm dvdsub mp2 sbc
aasc dvvideo mp2_at scpr
ac3 dxa mp2float screenpresso
ac3_at dxtory mp3 sdx2_dpcm
ac3_fixed dxv mp3_at sgi
acelp_kelvin eac3 mp3adu sgirle
adpcm_4xm eac3_at mp3adufloat sheervideo
adpcm_adx eacmv mp3float shorten
adpcm_afc eamad mp3on4 sipr
adpcm_agm eatgq mp3on4float siren
adpcm_aica eatgv mpc7 smackaud
adpcm_argo eatqi mpc8 smacker
adpcm_ct eightbps mpeg1_cuvid smc
adpcm_dtk eightsvx_exp mpeg1_v4l2m2m smvjpeg
adpcm_ea eightsvx_fib mpeg1video snow
adpcm_ea_maxis_xa escape124 mpeg2_crystalhd sol_dpcm
adpcm_ea_r1 escape130 mpeg2_cuvid sonic
adpcm_ea_r2 evrc mpeg2_mediacodec sp5x
adpcm_ea_r3 exr mpeg2_mmal speedhq
adpcm_ea_xas ffv1 mpeg2_qsv srgc
adpcm_g722 ffvhuff mpeg2_v4l2m2m srt
adpcm_g726 ffwavesynth mpeg2video ssa
adpcm_g726le fic mpeg4 stl
adpcm_ima_alp fits mpeg4_crystalhd subrip
adpcm_ima_amv flac mpeg4_cuvid subviewer
adpcm_ima_apc flashsv mpeg4_mediacodec subviewer1
adpcm_ima_apm flashsv2 mpeg4_mmal sunrast
adpcm_ima_cunning flic mpeg4_v4l2m2m svq1
adpcm_ima_dat4 flv mpegvideo svq3
adpcm_ima_dk3 fmvc mpl2 tak
adpcm_ima_dk4 fourxm msa1 targa
adpcm_ima_ea_eacs fraps mscc targa_y216
adpcm_ima_ea_sead frwu msmpeg4_crystalhd tdsc
adpcm_ima_iss g2m msmpeg4v1 text
adpcm_ima_mtf g723_1 msmpeg4v2 theora
adpcm_ima_oki g729 msmpeg4v3 thp
adpcm_ima_qt gdv msrle tiertexseqvideo
adpcm_ima_qt_at gif mss1 tiff
adpcm_ima_rad gremlin_dpcm mss2 tmv
adpcm_ima_smjpeg gsm msvideo1 truehd
adpcm_ima_ssi gsm_ms mszh truemotion1
adpcm_ima_wav gsm_ms_at mts2 truemotion2
adpcm_ima_ws h261 mv30 truemotion2rt
adpcm_ms h263 mvc1 truespeech
adpcm_mtaf h263_v4l2m2m mvc2 tscc
adpcm_psx h263i mvdv tscc2
adpcm_sbpro_2 h263p mvha tta
adpcm_sbpro_3 h264 mwsc twinvq
adpcm_sbpro_4 h264_crystalhd mxpeg txd
adpcm_swf h264_cuvid nellymoser ulti
adpcm_thp h264_mediacodec nuv utvideo
adpcm_thp_le h264_mmal on2avc v210
adpcm_vima h264_qsv opus v210x
adpcm_xa h264_rkmpp paf_audio v308
adpcm_yamaha h264_v4l2m2m paf_video v408
adpcm_zork hap pam v410
agm hca pbm vb
aic hcom pcm_alaw vble
alac hevc pcm_alaw_at vc1
alac_at hevc_cuvid pcm_bluray vc1_crystalhd
alias_pix hevc_mediacodec pcm_dvd vc1_cuvid
als hevc_qsv pcm_f16le vc1_mmal
amr_nb_at hevc_rkmpp pcm_f24le vc1_qsv
amrnb hevc_v4l2m2m pcm_f32be vc1_v4l2m2m
amrwb hnm4_video pcm_f32le vc1image
amv hq_hqa pcm_f64be vcr1
anm hqx pcm_f64le vmdaudio
ansi huffyuv pcm_lxf vmdvideo
ape hymt pcm_mulaw vmnc
apng iac pcm_mulaw_at vorbis
aptx idcin pcm_s16be vp3
aptx_hd idf pcm_s16be_planar vp4
arbc iff_ilbm pcm_s16le vp5
ass ilbc pcm_s16le_planar vp6
asv1 ilbc_at pcm_s24be vp6a
asv2 imc pcm_s24daud vp6f
atrac1 imm4 pcm_s24le vp7
atrac3 imm5 pcm_s24le_planar vp8
atrac3al indeo2 pcm_s32be vp8_cuvid
atrac3p indeo3 pcm_s32le vp8_mediacodec
atrac3pal indeo4 pcm_s32le_planar vp8_qsv
atrac9 indeo5 pcm_s64be vp8_rkmpp
aura interplay_acm pcm_s64le vp8_v4l2m2m
aura2 interplay_dpcm pcm_s8 vp9
avrn interplay_video pcm_s8_planar vp9_cuvid
avrp jacosub pcm_u16be vp9_mediacodec
avs jpeg2000 pcm_u16le vp9_qsv
avui jpegls pcm_u24be vp9_rkmpp
ayuv jv pcm_u24le vp9_v4l2m2m
bethsoftvid kgv1 pcm_u32be vplayer
bfi kmvc pcm_u32le vqa
bink lagarith pcm_u8 wavpack
binkaudio_dct libaom_av1 pcm_vidc wcmv
binkaudio_rdft libaribb24 pcx webp
bintext libcelt pgm webvtt
bitpacked libcodec2 pgmyuv wmalossless
bmp libdav1d pgssub wmapro
bmv_audio libdavs2 pictor wmav1
bmv_video libfdk_aac pixlet wmav2
brender_pix libgsm pjs wmavoice
c93 libgsm_ms png wmv1
cavs libilbc ppm wmv2
ccaption libopencore_amrnb prores wmv3
cdgraphics libopencore_amrwb prosumer wmv3_crystalhd
cdtoons libopenh264 psd wmv3image
cdxl libopenjpeg ptx wnv1
cfhd libopus qcelp wrapped_avframe
cinepak librsvg qdm2 ws_snd1
clearvideo libspeex qdm2_at xan_dpcm
cljr libvorbis qdmc xan_wc3
cllc libvpx_vp8 qdmc_at xan_wc4
comfortnoise libvpx_vp9 qdraw xbin
cook libzvbi_teletext qpeg xbm
cpia loco qtrle xface
cscd lscr r10k xl
cyuv m101 r210 xma1
dca mace3 ra_144 xma2
dds mace6 ra_288 xpm
derf_dpcm magicyuv ralf xsub
dfa mdec rasc xwd
dirac metasound rawvideo y41p
dnxhd microdvd realtext ylc
dolby_e mimic rl2 yop
dpx mjpeg roq yuv4
dsd_lsbf mjpeg_cuvid roq_dpcm zero12v
dsd_lsbf_planar mjpeg_qsv rpza zerocodec
dsd_msbf mjpegb rscc zlib
dsd_msbf_planar mlp rv10 zmbv
dsicinaudio mmvideo rv20
dsicinvideo motionpixels rv30
dss_sp movtext rv40
abench colorhold il selectivecolor
abitscope colorkey inflate sendcmd
acompressor colorkey_opencl interlace separatefields
acontrast colorlevels interleave setdar
acopy colormatrix join setfield
acrossfade colorspace kerndeint setparams
acrossover compand ladspa setpts
acrusher compensationdelay lagfun setrange
acue concat lenscorrection setsar
addroi convolution lensfun settb
adeclick convolution_opencl libvmaf sharpness_vaapi
adeclip convolve life showcqt
adelay copy limiter showfreqs
aderivative coreimage loop showinfo
adrawgraph coreimagesrc loudnorm showpalette
aecho cover_rect lowpass showspatial
aemphasis crop lowshelf showspectrum
aeval cropdetect lumakey showspectrumpic
aevalsrc crossfeed lut showvolume
afade crystalizer lut1d showwaves
afftdn cue lut2 showwavespic
afftfilt curves lut3d shuffleframes
afifo datascope lutrgb shuffleplanes
afir dcshift lutyuv sidechaincompress
afirsrc dctdnoiz lv2 sidechaingate
aformat deband mandelbrot sidedata
agate deblock maskedclamp sierpinski
agraphmonitor decimate maskedmax signalstats
ahistogram deconvolve maskedmerge signature
aiir dedot maskedmin silencedetect
aintegral deesser maskedthreshold silenceremove
ainterleave deflate maskfun sinc
alimiter deflicker mcdeint sine
allpass deinterlace_qsv mcompand smartblur
allrgb deinterlace_vaapi median smptebars
allyuv dejudder mergeplanes smptehdbars
aloop delogo mestimate sobel
alphaextract denoise_vaapi metadata sobel_opencl
alphamerge derain midequalizer sofalizer
amerge deshake minterpolate spectrumsynth
ametadata deshake_opencl mix split
amix despill movie spp
amovie detelecine mpdecimate sr
amplify dilation mptestsrc ssim
amultiply dilation_opencl negate stereo3d
anequalizer displace nlmeans stereotools
anlmdn dnn_processing nlmeans_opencl stereowiden
anlms doubleweave nnedi streamselect
anoisesrc drawbox noformat subtitles
anull drawgraph noise super2xsai
anullsink drawgrid normalize superequalizer
anullsrc drawtext null surround
apad drmeter nullsink swaprect
aperms dynaudnorm nullsrc swapuv
aphasemeter earwax ocr tblend
aphaser ebur128 ocv telecine
apulsator edgedetect openclsrc testsrc
arealtime elbg oscilloscope testsrc2
aresample entropy overlay thistogram
areverse eq overlay_cuda threshold
arnndn equalizer overlay_opencl thumbnail
aselect erosion overlay_qsv thumbnail_cuda
asendcmd erosion_opencl overlay_vulkan tile
asetnsamples extractplanes owdenoise tinterlace
asetpts extrastereo pad tlut2
asetrate fade pad_opencl tmedian
asettb fftdnoiz pal100bars tmix
ashowinfo fftfilt pal75bars tonemap
asidedata field palettegen tonemap_opencl
asoftclip fieldhint paletteuse tonemap_vaapi
asplit fieldmatch pan tpad
asr fieldorder perms transpose
ass fifo perspective transpose_npp
astats fillborders phase transpose_opencl
astreamselect find_rect photosensitivity transpose_vaapi
asubboost firequalizer pixdesctest treble
atadenoise flanger pixscope tremolo
atempo flite pp trim
atrim floodfill pp7 unpremultiply
avectorscope format premultiply unsharp
avgblur fps prewitt unsharp_opencl
avgblur_opencl framepack prewitt_opencl uspp
avgblur_vulkan framerate procamp_vaapi v360
axcorrelate framestep program_opencl vaguedenoiser
azmq freezedetect pseudocolor vectorscope
bandpass freezeframes psnr vflip
bandreject frei0r pullup vfrdet
bass frei0r_src qp vibrance
bbox fspp random vibrato
bench gblur readeia608 vidstabdetect
bilateral geq readvitc vidstabtransform
biquad gradfun realtime vignette
bitplanenoise graphmonitor remap vmafmotion
blackdetect greyedge removegrain volume
blackframe haas removelogo volumedetect
blend haldclut repeatfields vpp_qsv
bm3d haldclutsrc replaygain vstack
boxblur hdcd resample w3fdif
boxblur_opencl headphone reverse waveform
bs2b hflip rgbashift weave
bwdif highpass rgbtestsrc xbr
cas highshelf roberts xfade
cellauto hilbert roberts_opencl xfade_opencl
channelmap histeq rotate xmedian
channelsplit histogram rubberband xstack
chorus hqdn3d sab yadif
chromaber_vulkan hqx scale yadif_cuda
chromahold hstack scale2ref yaepblur
chromakey hue scale_cuda yuvtestsrc
chromashift hwdownload scale_npp zmq
ciescope hwmap scale_qsv zoompan
codecview hwupload scale_vaapi zscale
color hwupload_cuda scale_vulkan
colorbalance hysteresis scroll
colorchannelmixer idet select
./configure --list-muxers
查看FFmpeg的封装,封装Muxing是指将压缩后的编码封装到一个容器格式中,我们输入./configure --list-muxers
来查看FFmpeg支持哪些容器格式:
从上面打印信息来看,FFmpeg支持生成裸流文件,如H.264,AAC, PCM
, 也支持一些常见的格式,如MP3, MP4, FLV, M3U8, WEBM
等
./configure --list-demuxers
查看FFmpeg的解封装。aa filmstrip loas rsd
aac fits lrc rso
ac3 flac lvf rtp
acm flic lxf rtsp
act flv m4v s337m
adf fourxm matroska sami
adp frm mgsts sap
ads fsb microdvd sbc
adx fwse mjpeg sbg
aea g722 mjpeg_2000 scc
afc g723_1 mlp sdp
aiff g726 mlv sdr2
aix g726le mm sds
alp g729 mmf sdx
amr gdv mov segafilm
amrnb genh mp3 ser
amrwb gif mpc shorten
anm gsm mpc8 siff
apc gxf mpegps sln
ape h261 mpegts smacker
apm h263 mpegtsraw smjpeg
apng h264 mpegvideo smush
aptx hca mpjpeg sol
aptx_hd hcom mpl2 sox
aqtitle hevc mpsub spdif
argo_asf hls msf srt
asf hnm msnwc_tcp stl
asf_o ico mtaf str
ass idcin mtv subviewer
ast idf musx subviewer1
au iff mv sup
av1 ifv mvi svag
avi ilbc mxf swf
avisynth image2 mxg tak
avr image2_alias_pix nc tedcaptions
avs image2_brender_pix nistsphere thp
avs2 image2pipe nsp threedostr
bethsoftvid image_bmp_pipe nsv tiertexseq
bfi image_dds_pipe nut tmv
bfstm image_dpx_pipe nuv truehd
bink image_exr_pipe ogg tta
bintext image_gif_pipe oma tty
bit image_j2k_pipe paf txd
bmv image_jpeg_pipe pcm_alaw ty
boa image_jpegls_pipe pcm_f32be v210
brstm image_pam_pipe pcm_f32le v210x
c93 image_pbm_pipe pcm_f64be vag
caf image_pcx_pipe pcm_f64le vapoursynth
cavsvideo image_pgm_pipe pcm_mulaw vc1
cdg image_pgmyuv_pipe pcm_s16be vc1t
cdxl image_pictor_pipe pcm_s16le vividas
cine image_png_pipe pcm_s24be vivo
codec2 image_ppm_pipe pcm_s24le vmd
codec2raw image_psd_pipe pcm_s32be vobsub
concat image_qdraw_pipe pcm_s32le voc
dash image_sgi_pipe pcm_s8 vpk
data image_sunrast_pipe pcm_u16be vplayer
daud image_svg_pipe pcm_u16le vqf
dcstr image_tiff_pipe pcm_u24be w64
derf image_webp_pipe pcm_u24le wav
dfa image_xpm_pipe pcm_u32be wc3
dhav image_xwd_pipe pcm_u32le webm_dash_manifest
dirac ingenient pcm_u8 webvtt
dnxhd ipmovie pcm_vidc wsaud
dsf ircam pjs wsd
dsicin iss pmp wsvqa
dss iv8 pp_bnk wtv
dts ivf pva wv
dtshd ivr pvf wve
dv jacosub qcp xa
dvbsub jv r3d xbin
dvbtxt kux rawvideo xmv
dxa kvag realtext xvag
ea libgme redspark xwma
ea_cdata libmodplug rl2 yop
eac3 libopenmpt rm yuv4mpegpipe
epaf live_flv roq
ffmetadata lmlm4 rpl
从上面解封装又称为解复用格式的支持信息中可以看到,FFmpeg支持的demuxter非常多,包含图片image, MP3, FLV, MP4, MOV, AVI
等
./configure --list-protocols
查看FFmpeg的流媒体协议。(FFmpeg不仅仅支持本地的多媒体处理,而且还支持网络流媒体的处理):从支持的协议列表中可以看到,FFmpeg支持的流媒体协议比较多,包括MMS, HTTP, HTTPS, HLS, RTMP, RTP
,甚至支持TCP
,UDP
,其也支持使用file协议的本地文件操作和使用concat协议支持的多个文件串流操作。
接下我们可以尝试输入:./configure --list-parsers
查看FFmpeg支持的解析器
./configure --list-bsfs
查看FFmpeg支持的字节流过滤器