个人ffmpeg笔记(一)

环境安装

QT环境安装

  1. 运行qt...run安装

下载地址:https://download.qt.io/archive/qt/

下载地址:https://download.qt.io/archive/qt/5.12/5.12.10/

  1. sudo apt install --reinstall libxcb-xinerama0 解决xcb问题

  2. Ubuntu16.04打开Qt显示/home/user/.config/QtProject/qtcreator/qtversion.xml :Permission denied

    权限不够所导致,执⾏命令 sudo chown -R user:user ~/.config/ 即可解决

ffmpeg环境安装

apt安装:

sudo apt-get update
sudo apt-get install -y \
  autoconf \
  automake \
  build-essential \
  cmake \
  git-core \
  libass-dev \
  libfreetype6-dev \
  libsdl2-dev \
  libtool \
  libva-dev \
  libvdpau-dev \
  libvorbis-dev \
  libxcb1-dev \
  libxcb-shm0-dev \
  libxcb-xfixes0-dev \
  libfdk-aac-dev \
  libfaad-dev \
  pkg-config \
  texinfo \
  wget \
  zlib1g-dev

sudo apt-get install -y \
	nasm \
	yasm \
	libx264-dev \
	libx265-dev \
	libnuma-dev \
	libvpx-dev \
	libfdk-aac-dev \
	libmp3lame-dev \
	libopus-dev 

apt安装:

sudo apt install ffmpeg
vi  ~/.bashrc
export PATH="/usr/bin:$PATH"
source ~/.bashrc

源码安装:

一、创建目录
在home目录下创建
ffmpeg_sources:用于下载源文件
ffmpeg_build: 存储编译后的库文件
bin:存储二进制文件(ffmpeg,ffplay,ffprobe,X264,X265等)
cd ~
mkdir ffmpeg_sources ffmpeg_build bin

二、安装依赖
sudo apt-get update
sudo apt-get -y install \
autoconf \
automake \
build-essential \
cmake \
git-core \
libass-dev \
libfreetype6-dev \
libsdl2-dev \
libtool \
libva-dev \
libvdpau-dev \
libvorbis-dev \
libxcb1-dev \
libxcb-shm0-dev \
libxcb-xfixes0-dev \
pkg-config \
texinfo \
wget \
zlib1g-dev

NASM使用源码进行安装
cd ~/ffmpeg_sources && \
wget https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.bz2 && \
tar xjvf nasm-2.14.02.tar.bz2 && \
cd nasm-2.14.02 && \
./autogen.sh && \
PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" &&
\
make && \
make install

Yasm使用源码进行安装:
cd ~/ffmpeg_sources && \
wget -O yasm-1.3.0.tar.gz https://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz && \
tar xzvf yasm-1.3.0.tar.gz && \
cd yasm-1.3.0 && \
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" && \
make && \
make install

libx264
H.264视频编码器。更多信息和使用范例参考H.264 Encoding Guide
要求编译ffmpeg时配置:--enable-gpl --enable-libx264.
使用源码进行编译:
cd ~/ffmpeg_sources && \
git -C x264 pull 2> /dev/null || git clone --depth 1 https://gitee.com/ibaoger/x264.git && \
cd x264 && \
PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" && \
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-static --enable-pic && \
PATH="$HOME/bin:$PATH" make && \
make install

libx265
H.265/HEVC 视频编码器, 更多信息和使用范例参考H.265 Encoding Guide。
要求编译ffmpeg时配置:--enable-gpl --enable-libx265.
使用源码进行编译:
sudo apt-get install mercurial libnuma-dev && \
cd ~/ffmpeg_sources && git clone https://gitee.com/mirrors_videolan/x265.git && \
cd x265/build/linux && \
PATH="$HOME/bin:$PATH" cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$HOME/ffmpeg_build" -DENABLE_SHARED=off ../../source && \
PATH="$HOME/bin:$PATH" make && \
make install

libvpx
VP8/VP9视频编解码器。 更多信息和使用范例参考VP9 Video Encoding Guide 。
要求编译ffmpeg时配置: --enable-libvpx.
使用源码进行编译:
cd ~/ffmpeg_sources && \
git -C libvpx pull 2> /dev/null || git clone --depth 1 https://github.com/webmproject/libvpx.git && \
cd libvpx && \
PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic && \
PATH="$HOME/bin:$PATH" make && \
make install

libfdk-aac
AAC音频编码器. 更多信息和使用范例参考AAC Audio Encoding Guide。
要求编译ffmpeg时配置:--enable-libfdk-aac ( 如果你已经配置了 --enable-gpl则需要加上--enablenonfree).
使用源码进行编译:
cd ~/ffmpeg_sources && \
git -C fdk-aac pull 2> /dev/null || git clone --depth 1 https://github.com/mstorsjo/fdk-aac && \
cd fdk-aac && \
autoreconf -fiv && \
./configure CFLAGS=-fPIC --prefix="$HOME/ffmpeg_build" && \
make && \
make install

libmp3lame
MP3音频编码器.
要求编译ffmpeg时配置:--enable-libmp3lame.
使用源码进行编译:
cd ~/ffmpeg_sources && \
git clone --depth 1 https://gitee.com/qingfuliao/lame && \
cd lame && \
PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-nasm --with-pic && \
PATH="$HOME/bin:$PATH" make && \
make install

libopus
Opus音频编解码器.
要求编译ffmpeg时配置:--enable-libopus.
使用源码进行编译:
cd ~/ffmpeg_sources && \
git -C opus pull 2> /dev/null || git clone --depth 1 https://gitee.com/ttsu00/opus.git && \
cd opus && \
./autogen.sh && \
./configure --prefix="$HOME/ffmpeg_build" -with-pic&& \
make && \
make install

FFmpeg
cd ~/ffmpeg_sources && \
wget -O ffmpeg-4.2.1.tar.bz2 https://ffmpeg.org/releases/ffmpeg-4.2.1.tar.bz2 && \
tar xjvf ffmpeg-4.2.1.tar.bz2 && \
cd ffmpeg-4.2.1 && \
PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" CFLAGS="-O3 -fPIC" ./configure \
--prefix="$HOME/ffmpeg_build" \
--pkg-config-flags="--static" \
--extra-cflags="-I$HOME/ffmpeg_build/include" \
--extra-ldflags="-L$HOME/ffmpeg_build/lib" \
--extra-libs="-lpthread -lm" \
--bindir="$HOME/bin" \
--enable-gpl \
--enable-libass \
--enable-libfdk-aac \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libopus \
--enable-libvorbis \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-openssl \
--enable-pic \
--enable-shared \
--enable-nonfree \
--enable-debug=3 \
--disable-optimizations \
--disable-asm \
--disable-stripping && \
PATH="$HOME/bin:$PATH" make && \
make install && \
hash -r
然后重新登录系统或者在当前shell会话执行如下命令以识别新安装ffmpeg的位置:
source ~/.profile
现在已经完成编译和安装ffmpeg (also ffplay, ffprobe, lame, x264, & x265) 。该文档剩余章节主要讲如何更新和删除ffmepg。
编译完成后,ffmpeg_build ffmpeg_sources bin目录的大体情况

加入命令:
vi ~/.bashrc
export PATH="$PATH:/usr/local/bin"   这里需要写入正确路径
source ~/.bashrc

环境使用

Cmake
cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(ffmpeg_test)

# 设置C标准
set(CMAKE_C_STANDARD 99)

# 查找FFmpeg库
find_package(PkgConfig REQUIRED)
pkg_check_modules(AVFORMAT REQUIRED libavformat)
pkg_check_modules(AVCODEC REQUIRED libavcodec)
pkg_check_modules(AVUTIL REQUIRED libavutil)
pkg_check_modules(AVDEVICE REQUIRED libavdevice)
pkg_check_modules(AVFILTER REQUIRED libavfilter)
pkg_check_modules(POSTPROC REQUIRED libpostproc)
pkg_check_modules(SWRESAMPLE REQUIRED libswresample)
pkg_check_modules(SWSCALE REQUIRED libswscale)

find_package(SDL2 REQUIRED)
link_libraries(SDL2)

# 包含FFmpeg头文件路径
include_directories(${AVFORMAT_INCLUDE_DIRS})
include_directories(${AVCODEC_INCLUDE_DIRS})
include_directories(${AVUTIL_INCLUDE_DIRS})
include_directories(${AVDEVICE_INCLUDE_DIRS})
include_directories(${AVFILTER_INCLUDE_DIRS})
include_directories(${POSTPROC_INCLUDE_DIRS})
include_directories(${SWRESAMPLE_INCLUDE_DIRS})
include_directories(${SWSCALE_INCLUDE_DIRS})

# 添加可执行文件
add_executable(ffmpeg_test main.cpp)

# 链接FFmpeg库
target_link_libraries(ffmpeg_muxmp4 ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES} ${AVDEVICE_LIBRARIES} ${AVFILTER_LIBRARIES} ${POSTPROC_LIBRARIES} ${SWRESAMPLE_LIBRARIES}  ${SWSCALE_LIBRARIES} )
QT
CONFIG += link_pkgconfig
PKGCONFIG += sdl2

LIBS += -L/home/enpht/sdk/ffmpeg4/ffmpeg_build/lib/ -lavcodec -lavformat -lavutil -lswscale -lavfilter -lavdevice -lswresample -lfdk-aac
INCLUDEPATH += /home/enpht/sdk/ffmpeg4/ffmpeg_build/include
DEPENDPATH += /home/enpht/sdk/ffmpeg4/ffmpeg_build/include
qmake 复制代码
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp \
    muxer.cpp \
    audioencoder.cpp \
    videoencoder.cpp \
    audioresampler.cpp

win32 {
INCLUDEPATH += $$PWD/ffmpeg-4.2.1-win32-dev/include
LIBS += $$PWD/ffmpeg-4.2.1-win32-dev/lib/avformat.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avcodec.lib    \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avdevice.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avfilter.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avutil.lib     \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/postproc.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/swresample.lib \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/swscale.lib
}

linux{
INCLUDEPATH += /usr/include/x86_64-linux-gnu/libavcodec /usr/include/x86_64-linux-gnu/libavformat /usr/include/x86_64-linux-gnu/libavutil /usr/include/x86_64-linux-gnu/libswscale

LIBS += -lavcodec -lavformat -lavutil -lswscale

}

HEADERS += \
    muxer.h \
    audioencoder.h \
    videoencoder.h \
    audioresampler.h

源码编译:

下载源码:

mkdir ffmpeg && cd ffmpeg/
wget https://ffmpeg.org/releases/ffmpeg-4.3.1.tar.bz2
tar xvf ffmpeg-4.3.1.tar.bz2
cd ffmpeg-4.3.1/

配置:

./configure --enable-gpl \
  --enable-libass \
  --enable-libfdk-aac \
  --enable-libfreetype \
  --enable-libopus \
  --enable-libvorbis \
  --enable-libvpx \
  --enable-libx264 \
  --enable-libx265 \
  --enable-nonfree

编译:

sudo make -j4 && sudo make install

测试:

ffmpeg -version

零声安装步骤参考:

https://www.yuque.com/linuxer/ffmcy9/pgx8mi

QT使用ffmpeg

pro文件:

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += \
main.c
INCLUDEPATH += /home/lqf/ffmpeg_build/include

LIBS += /home/lqf/ffmpeg_build/lib/libavcodec.a \
/home/lqf/ffmpeg_build/lib/libavdevice.a \
/home/lqf/ffmpeg_build/lib/libavfilter.a \
/home/lqf/ffmpeg_build/lib/libavformat.a \
/home/lqf/ffmpeg_build/lib/libavutil.a \
/home/lqf/ffmpeg_build/lib/libswresample.a \
/home/lqf/ffmpeg_build/lib/libswscale.a

兼容多个平台:可以参考飞扬青云的playffmpeg

tex 复制代码
#如果用的是ffmpeg4内核请将ffmpeg3改成ffmpeg4,两种内核不兼容,头文件也不一样
DEFINES += ffmpeg4

#ffmpeg4则使用ffmpeg4的目录

contains(DEFINES, ffmpeg4) {
strPath = ffmpeg4
} else {
strPath = ffmpeg3
}

#表示64位的构建套件
contains(QT_ARCH, x86_64) {
strLib = winlib64
strInclude = include64
} else {
#由于Qt4不支持QT_ARCH所以会执行下面的
#如果用的64位的Qt4则需要自行修改

strLib = winlib
strInclude = include
}

#表示arm平台构建套件

contains(QT_ARCH, arm) {
strInclude = include
}

!android {
INCLUDEPATH += $$PWD/$$strPath/$$strInclude
}

win32 {
LIBS += -L$$PWD/$$strPath/$$strLib/ -lavcodec -lavfilter -lavformat -lswscale -lavutil -lswresample -lavdevice
}

#请自行替换

!android {
unix:!macx {
LIBS += -L$$PWD/linuxlib/ -lavfilter -lavformat -lavdevice -lavcodec -lswscale -lavutil -lswresample -lavdevice -lpthread -lm -lz -lrt -ldl
}}

#android系统
android {
INCLUDEPATH += $$PWD/androidlib/include
LIBS += -L$$PWD/androidlib/ -lavcodec -lavfilter -lavformat -lswscale -lavutil -lswresample
#将动态库文件一起打包
ANDROID_EXTRA_LIBS += $$PWD/androidlib/libavcodec.so
ANDROID_EXTRA_LIBS += $$PWD/androidlib/libavfilter.so
ANDROID_EXTRA_LIBS += $$PWD/androidlib/libavformat.so
ANDROID_EXTRA_LIBS += $$PWD/androidlib/libavutil.so
ANDROID_EXTRA_LIBS += $$PWD/androidlib/libswresample.so
ANDROID_EXTRA_LIBS += $$PWD/androidlib/libswscale.so
}

pkgconfig查找:

# 使用 pkg-config 查找 FFmpeg 4 的库
CONFIG += link_pkgconfig
PKGCONFIG += libavcodec libavformat libavutil libswscale

# 如果需要使用其他 FFmpeg 组件,可以添加它们
# PKGCONFIG += libavfilter libavdevice libavformat libswresample

# 添加包含目录
INCLUDEPATH += $$system(pkg-config --cflags-only-I libavcodec libavformat libavutil libswscale)

# 添加库目录
LIBS += $$system(pkg-config --libs libavcodec libavformat libavutil libswscale)

我的具体位置:

CONFIG += link_pkgconfig
PKGCONFIG += sdl2

LIBS += -L/home/enpht/sdk/ffmpeg4/ffmpeg_build/lib/ -lavcodec -lavformat -lavutil -lswscale -lavfilter -lavdevice -lswresample -lfdk-aac
INCLUDEPATH += /home/enpht/sdk/ffmpeg4/ffmpeg_build/include
DEPENDPATH += /home/enpht/sdk/ffmpeg4/ffmpeg_build/include

头文件导入

cpp 复制代码
//必须加以下内容,否则编译不能通过,为了兼容C和C99标准
#ifndef INT64_C
#define INT64_C
#define UINT64_C
#endif

//引入ffmpeg头文件
extern "C" {
#include "libavutil/opt.h"
#include "libavutil/time.h"
#include "libavutil/frame.h"
#include "libavutil/pixdesc.h"
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
#include "libavutil/ffversion.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h" 
#include "libswresample/swresample.h" 
#include "libavformat/avformat.h" 
#include "libavfilter/avfilter.h" 

#ifdef ffmpegdevice 
#include "libavdevice/avdevice.h" 
#endif

#ifndef gcc45 
#include "libavutil/hwcontext.h" 
//#include "libavutil/hwcontext_qsv.h" 
#endif 
}

ffmpeg命令行

主要命令参数:

命令参数 内容 命令参数 内容
-version 显示版本 -bsfs 显示可用比特流filter
-buildconf 显示编译配置 -protocols 显示可用的协议
-formats 显示可用格式 (muxers+demuxers) -filters 显示可用的过滤器
-muxers 显示可用复用器 -pix_fmts 显示可用的像素格式
-demuxers 显示可用解复用器 -layouts 显示标准声道名称
-codecs 显示可用编解码器 (decoders+encoders) -sample_fmts 显示可用的音频采样 格式
-decoders 显示可用解码器 -colors 显示可用的颜色名称
-encoders 显示可用编码器

查看具体所支持的类型:

语法:

​ ffmepg -h type=name

比如:

​ ffmpeg -h muxer=flv

​ ffmpeg -h filter=atempo (atempo调整音频播放速率)

​ ffmpeg -h encoder=libx264

ffmpeg/ffplay/ffprobe3区别

◼ffmpeg:

Hyper fast Audio and Video encoder

超快音视频编码器(类似爱剪辑)

◼ffplay:

Simple media player简单媒体播放器

◼ffprobe:

Simple multimedia streams analyzer

简单多媒体流分析器

◼基本信息: ffmpeg -h

◼高级信息: ffmpeg -h long

◼所有信息: ffmpeg -h full

ffplay命令

播放命令
选项 说明 选项 说明
q, ESC 退出播放 t 循环切换字幕流
f 全屏切换 c 循环切换节目
p, SPC 暂停 w 循环切换过滤器或显 示模式
m 静音切换 s 逐帧播放
9, 0 9减少音量, 0增加音量 left/right 向后/向前拖动10秒
/, * /减少音量, *增加音量 down/up 向后/向前拖动1分钟
a 循环切换音频流 鼠标右键单击 拖动与显示宽度对应 百分比的文件进行播 放
v 循环切换视频流 鼠标左键双击 全屏切换
命令选项

◼ -x width 强制显示宽带。

◼ -y height 强制显示高度。

◼ -video_size size 帧尺寸 设置显示帧存储(WxH格式),仅适用于类似

原始YUV等没有包含帧大小(WxH)的视频。

比如: ffplay -pixel_format yuv420p -video_size 320x240 -framerate 5 yuv420p_320x240.yuv

◼ -pixel_format format 格式设置像素格式。

◼ -fs 以全屏模式启动。

◼ -an 禁用音频(不播放声音)

◼ -vn 禁用视频(不播放视频)

◼ -sn 禁用字幕(不显示字幕)

◼ -ss pos 根据设置的秒进行定位拖动,注意时间单位:比如'55' 55seconds, '12:03:45' ,12 hours, 03 minutes and 45 seconds, '23.189' 23.189second

◼ -t duration 设置播放视频/音频长度,时间单位如 -ss选项

◼ -bytes 按字节进行定位拖动(0=off 1=on -1=auto)。

◼ -seek_interval interval 自定义左/右键定位拖动间隔(以秒为单位),默认值为10秒(代码没有看到实现)

◼ -nodisp 关闭图形化显示窗口,视频将不显示

◼ -noborder 无边框窗口

◼ -volume vol 设置起始音量。音量范围[0 ~100]

◼ -f fmt 强制使用设置的格式进行解析。比如-f s16le

◼ -window_title title 设置窗口标题(默认为输入文件名)

◼ -loop number 设置播放循环次数

◼ -showmode mode 设置显示模式,可用的模式值: 0 显示视频,1 显示音频波形, 2 显示音频频谱。缺省为0,如果视频不存在则自动选择2

◼ -vf filtergraph 设置视频滤镜

◼ -af filtergraph 设置音频滤镜

◼ -stats 打印多个回放统计信息,包括显示流持续时间,编解码器参数,流中的当前位置,以及音频/视频同步差值。默认情况下处于启用状态,要显式禁用它则需要指定-nostats。。

◼ -fast 非标准化规范的多媒体兼容优化。

◼ -genpts 生成pts。

◼ -sync type 同步类型 将主时钟设置为audio(type=audio), video(type=video)或external(type=ext),默认是audio为主时钟。

◼ -ast audio_stream_specifier 指定音频流索引,比如-ast 3,播放流索引为3的音频流

◼ -vst video_stream_specifier指定视频流索引,比如-vst 4,播放流索引为4的视频流

◼ -sst subtitle_stream_specifier 指定字幕流索引,比如-sst 5,播放流索引为5的字幕流

◼ -autoexit 视频播放完毕后退出。

◼ -exitonkeydown 键盘按下任何键退出播放

◼ -exitonmousedown 鼠标按下任何键退出播放

◼ -codec:media_specifier codec_name 强制使用设置的多媒体解码器,media_specifier可用值为a(音频), v(视频)和s字幕。比如-codec:v h264_qsv 强制视频采用h264_qsv解码

◼ -acodec codec_name 强制使用设置的音频解码器进行音频解码

◼ -vcodec codec_name 强制使用设置的视频解码器进行视频解码

◼ -scodec codec_name 强制使用设置的字幕解码器进行字幕解码

◼ -autorotate 根据文件元数据自动旋转视频。值为0或1 ,默认为1。

◼ -framedrop 如果视频不同步则丢弃视频帧。当主时钟非视频时钟时默认开启。若需禁用则使用 -noframedrop

◼ -infbuf 不限制输入缓冲区大小。尽可能快地从输入中读取尽可能多的数据。播放实时流时默认启用,如果未及时读取数据,则可能会丢弃数据。此选项将不限制缓冲区的大小。若需禁用则使用-noinfbuf

播放例子

◼ 播放本地文件

◼ ffplay -window_title "test time" -ss 2 -t 10 -autoexit test.mp4

◼ ffplay buweishui.mp3

◼ 播放网络流

◼ ffplay -window_title "rtmp stream"

rtmp://202.69.69.180:443/webcast/bshdlive-pc

◼ 强制解码器

◼ mpeg4解码器: ffplay -vcodec mpeg4 test.mp4

◼ h264解码器: ffplay -vcodec h264 test.mp4

◼ 禁用音频或视频

◼ 禁用音频: ffplay test.mp4 -an

◼ 禁用视频: ffplay test.mp4 -vn

◼ 播放YUV数据

◼ ffplay -pixel_format yuv420p -video_size 320x240 -framerate 5

yuv420p_320x240.yuv

◼ 播放RGB数据

◼ ffplay -pixel_format rgb24 -video_size 320x240 -i rgb24_320x240.rgb

◼ ffplay -pixel_format rgb24 -video_size 320x240 -framerate 5 -i rgb24_320x240.rgb

◼ 播放PCM数据

◼ ffplay -ar 48000 -ac 2 -f f32le 48000_2_f32le.pcm

-ar set audio sampling rate (in Hz) (from 0 to INT_MAX) (default 0)

-ac set number of audio channels (from 0 to INT_MAX) (default 0)

过滤器

◼ 视频旋转

ffplay -i test.mp4 -vf transpose=1

◼ 视频反转

ffplay test.mp4 -vf hflip

ffplay test.mp4 -vf vflip

◼ 视频旋转和反转

ffplay test.mp4 -vf hflip,transpose=1

◼ 音频变速播放

ffplay -i test.mp4 -af atempo=2

◼ 视频变速播放

ffplay -i test.mp4 -vf setpts=PTS/2

◼ 音视频同时变速

ffplay -i test.mp4 -vf setpts=PTS/2 -af atempo=2

ffmpeg命令

主要命令

◼ 主要参数:

-i 设定输入流

-f 设定输出格式(format)

-ss 开始时间

-t 时间长度

◼ 视频参数:

-vframes 设置要输出的视频帧数

-b 设定视频码率

-b:v 视频码率

-r 设定帧速率

-s 设定画面的宽与高

-vn 不处理视频

-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777

-vcodec 设定视频编解码器,如果用copy表示原始编解码数据必须被拷贝

-vf 视频过滤器

◼ 音频参数:

-aframes 设置要输出的音频帧数

-b:a 音频码率

-ar 设定采样率

-ac 设定声音的Channel数

-acodec 设定声音编解码器,如果用copy表示原始编解码数据必须被拷贝。

-an 不处理音频

-af 音频过滤器

例子
修改参数

◼ 修改mp4视频参数,并且转码265:

ffmpeg -i test.mp4 -vframes 300 -b:v 300k -r 30 -s 640x480 -aspect 16:9 -vcodec libx265 out1.mp4

◼ 提取音频:

ffmpeg -i test.mp4 -b:a 192k -ar 48000 -ac 2 -acodec libmp3lame -aframes 200 out2.mp3

◼ 保留封装格式

纯音频:ffmpeg -i test.mp4 -acodec copy -vn audio.mp4

纯视频:ffmpeg -i test.mp4 -vcodec copy -an video.mp4

提取音视频

◼ 提取视频

保留编码格式: ffmpeg -i test.mp4 -vcodec copy -an test_copy.h264

强制格式: ffmpeg -i test.mp4 -vcodec libx264 -an test.h264

◼ 提取音频

保留编码格式: ffmpeg -i test.mp4 -acodec copy -vn test.aac

强制格式: ffmpeg -i test.mp4 -acodec libmp3lame -vn test.mp3

提取YUV和PCM

◼ 提取YUV

提取3秒数据,分辨率和源视频一致

ffmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p yuv420p_orig.yuv

提取3秒数据,分辨率转为320x240

ffmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p -s 320x240 yuv420p_320x240.yuv

◼ 提取RGB

提取3秒数据,分辨率转为320x240

ffmpeg -i test.mp4 -t 3 -pix_fmt rgb24 -s 320x240 rgb24_320x240.rgb

RGB和YUV之间的转换

ffmpeg -s 320x240 -pix_fmt yuv420p -i yuv420p_320x240.yuv -pix_fmt rgb24 rgb24_320x240_2.rgb

◼ 提取PCM

ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -f s16le 48000_2_s16le.pcm

ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -sample_fmt s16 out_s16.wav

ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -codec:a pcm_s16le out2_s16le.wav

ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -f f32le 48000_2_f32le.pcm

ffmpeg -i test.mp4 -t 10 -vn -ar 48000 -ac 2 -f f32le 48000_2_f32le_2.pcm

转封装

◼ 保持编码格式:

ffmpeg -i test.mp4 -vcodec copy -acodec copy test_copy.ts

ffmpeg -i test.mp4 -codec copy test_copy2.ts

◼ 改变编码格式:

ffmpeg -i test.mp4 -vcodec libx265 -acodec libmp3lame out_h265_mp3.mkv

◼ 修改帧率:

ffmpeg -i test.mp4 -r 15 -codec copy output.mp4 (错误命令)

ffmpeg -i test.mp4 -r 15 output2.mp4

◼ 修改视频码率:

ffmpeg -i test.mp4 -b 400k output_b.mkv (此时音频也被重新编码)

◼ 修改视频码率:

ffmpeg -i test.mp4 -b:v 400k output_bv.mkv

◼ 修改音频码率:

ffmpeg -i test.mp4 -b:a 192k output_ba.mp4

如果不想重新编码video,需要加上-vcodec copy

◼ 修改音视频码率:

ffmpeg -i test.mp4 -b:v 400k -b:a 192k output_bva.mp4

◼ 修改视频分辨率:

ffmpeg -i test.mp4 -s 480x270 output_480x270.mp4

◼ 修改音频采样率:

ffmpeg -i test.mp4 -ar 44100 output_44100hz.mp4

裁剪

◼ 找三个不同的视频每个视频截取10秒内容

ffmpeg -i 沙海02.mp4 -ss 00:05:00 -t 10 -codec copy 1.mp4

ffmpeg -i 复仇者联盟3.mp4 -ss 00:05:00 -t 10 -codec copy 2.mp4

ffmpeg -i 红海行动.mp4 -ss 00:05:00 -t 10 -codec copy 3.mp4

如果音视频格式不统一则强制统一为 -vcodec libx264 -acodec aac

◼ 将上述1.mp4/2.mp4/3.mp4转成ts格式

ffmpeg -i 1.mp4 -codec copy -vbsf h264_mp4toannexb 1.ts

ffmpeg -i 2.mp4 -codec copy -vbsf h264_mp4toannexb 2.ts

ffmpeg -i 3.mp4 -codec copy -vbsf h264_mp4toannexb 3.ts

分离某些封装格式(例如MP4/FLV/MKV等)中的H.264的时候,需要首先写入

SPS和PPS,否则会导致分离出来的数据没有SPS、 PPS而无法播放。 H.264码流

的SPS和PPS信息存储在AVCodecContext结构体的extradata中。需要使用ffmpeg

中名称为"h264_mp4toannexb"的bitstream filter处理

◼ 转成flv格式

ffmpeg -i 1.mp4 -codec copy 1.flv

ffmpeg -i 2.mp4 -codec copy 2.flv

ffmpeg -i 3.mp4 -codec copy 3.flv

合并

◼ 以MP4格式进行拼接

方法1: ffmpeg -i "concat:1.mp4|2.mp4|3.mp4" -codec copy out_mp4.mp4

方法2: ffmpeg -f concat -i mp4list.txt -codec copy out_mp42.mp4

◼ 以TS格式进行拼接

方法1: ffmpeg -i "concat:1.ts|2.ts|3.ts" -codec copy out_ts.mp4

方法2: ffmpeg -f concat -i tslist.txt -codec copy out_ts2.mp4

◼ 以FLV格式进行拼接

方法1: ffmpeg -i "concat:1.flv|2.flv|3.flv" -codec copy out_flv.mp4

方法2: ffmpeg -f concat -i flvlist.txt -codec copy out_flv2.mp4

◼ 方法1只适用部分封装格式,比如TS

◼ 建议:

(1)使用方法2进行拼接

(2)转成TS格式再进行拼接

◼ 修改音频编码

ffmpeg -i 2.mp4 -vcodec copy -acodec ac3 -vbsf h264_mp4toannexb 2.ts

ffmpeg -i "concat:1.ts|2.ts|3.ts" -codec copy out1.mp4 结果第二段没有声音

◼ 修改音频采样率

ffmpeg -i 2.mp4 -vcodec copy -acodec aac -ar 96000 -vbsf h264_mp4toannexb 2.ts

ffmpeg -i "concat:1.ts|2.ts|3.ts" -codec copy out2.mp4 第二段播放异常

◼ 修改视频编码格式

ffmpeg -i 1.mp4 -acodec copy -vcodec libx265 1.ts

ffmpeg -i "concat:1.ts|2.ts|3.ts" -codec copy out3.mp4

◼ 修改视频分辨率

ffmpeg -i 1.mp4 -acodec copy -vcodec libx264 -s 800x472 -vbsf h264_mp4toannexb 1.ts

ffmpeg -i "concat:1.ts|2.ts|3.ts" -codec copy out4.mp4

◼ 注意:

◼ 把每个视频封装格式也统一为ts,拼接输出的时候再输出你需要的封装格

式,比如MP4

◼ 视频分辨率可以不同,但是编码格式需要统一

◼ 音频编码格式需要统一,音频参数(采样率/声道等)也需要统一

图片和视频互转

◼ 截取一张图片

ffmpeg -i test.mp4 -y -f image2 -ss 00:00:02 -vframes 1 -s 640x360 test.jpg

ffmpeg -i test.mp4 -y -f image2 -ss 00:00:02 -vframes 1 -s 640x360 test.bmp

-i 输入

-y 覆盖

-f 格式

image2 一种格式

-ss 起始值

-vframes 帧 如果大于1 那么 输出加%03d test%03d.jpg

-s 格式大小size

◼ 转换视频为图片(每帧一张图):

ffmpeg -i test.mp4 -t 5 -s 640x360 -r 15 frame%03d.jpg

◼ 图片转换为视频:

ffmpeg -f image2 -i frame%03d.jpg -r 25 video.mp4

◼ 从视频中生成GIF图片

ffmpeg -i test.mp4 -t 5 -r 1 image1.gif

ffmpeg -i test.mp4 -t 5 -r 25 -s 640x360 image2.gif

◼ 将 GIF 转化为 视频

ffmpeg -f gif -i image2.gif image2.mp4

屏幕录制

◼ 先安装dshow软件 Screen Capturer Recorder,

项目地址: https://sourceforge.net/projects/screencapturer/files/

然后查看可用设备名字: ffmpeg -list_devices true -f dshow -i dummy

◼ 录制视频(默认参数)

桌面: ffmpeg -f dshow -i video="screen-capture-recorder" v-out.mp4

摄像头: ffmpeg -f dshow -i video="Integrated Webcam" -y v-out2.flv (要根据自己摄像头名称)

◼ 录制声音(默认参数)

系统声音: ffmpeg -f dshow -i audio="virtual-audio-capturer" a-out.aac

系统+麦克风声音: ffmpeg -f dshow -i audio="麦克风 (Realtek Audio)" -f dshow -i audio="virtual-audio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 a-out2.aac

◼ 同时录制声音和视频(默认参数)

ffmpeg -f dshow -i audio="麦克风 (Realtek Audio)" -f dshow -i audio="virtualaudio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f dshow -i video="screen-capture-recorder" -y av-out.flv

◼ 查看视频录制的可选参数

ffmpeg -f dshow -list_options true -i video="screen-capture-recorder"

◼ 查看视频录制的可选参数

ffmpeg -f dshow -list_options true -i audio="virtual-audio-capturer"

指定参数录制:

◼ ffmpeg -f dshow -i audio="麦克风 (Realtek Audio)" -f dshow -i

audio="virtual-audio-capturer" -filter_complex

amix=inputs=2:duration=first:dropout_transition=2 -f dshow -video_size

1920x1080 -framerate 15 -pixel_format yuv420p -i video="screen-capturerecorder" -vcodec h264_qsv -b:v 3M -y av-out.flv

◼ ffmpeg -f dshow -i audio="麦克风 (Realtek Audio)" -f dshow -i

audio="virtual-audio-capturer" -filter_complex

amix=inputs=2:duration=first:dropout_transition=2 -f dshow -i

video="screen-capture-recorder" -vcodec h264_qsv -b:v 3M -r 15 -y avout2.mp4

◼ ffmpeg -f dshow -i audio="麦克风 (Realtek Audio)" -f dshow -i

audio="virtual-audio-capturer" -filter_complex

amix=inputs=2:duration=first:dropout_transition=2 -f dshow -framerate 15

-pixel_format yuv420p -i video="screen-capture-recorder" -vcodec

h264_qsv -b:v 3M -r 15 -y av-out3.mp4

推流

◼ 直播拉流

ffplay rtmp://server/live/streamName

ffmpeg -i rtmp://server/live/streamName -c copy dump.flv

对于不是rtmp的协议 -c copy要谨慎使用

◼ 可用地址

HKS: rtmp://live.hkstv.hk.lxdns.com/live/hks2

大熊兔(点播): rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov

CCTV1高清: http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8

ffmpeg -i http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8 -c copy cctv1.ts

ffmpeg -i http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8 cctv1.flv

ffmpeg -i http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8 -acodec aac -vcodec libx264

cctv1-2.flv

CCTV3高清: http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8

CCTV5高清: http://ivi.bupt.edu.cn/hls/cctv5hd.m3u8

CCTV5+高清: http://ivi.bupt.edu.cn/hls/cctv5phd.m3u8

CCTV6高清: http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8

◼ 直播推流

ffmpeg -re -i out.mp4 -c copy flv rtmp://server/live/streamName

-re,表示按时间戳读取文件

◼ rtsp和rtmp推流

// rtsp推流(文件推流)
ffmpeg -re -i test.mp4 -rtsp_transport tcp -c copy -f rtsp rtsp://127.0.0.1:554/live/test

// rtsp推流(文件循环推流)
ffmpeg -re -stream_loop  -1  -i test.mp4 -rtsp_transport tcp -c copy -f rtsp rtsp://127.0.0.1:554/live/test

// rtmp推流(文件推流)
ffmpeg -re -i test.mp4 -vcodec h264_nvenc  -acodec aac -f flv  rtmp://192.168.1.3:1935/live/test

// rtmp推流(文件循环推流)
ffmpeg -re -stream_loop  -1 -i test.mp4 -vcodec h264  -acodec aac -f flv  rtmp://127.0.0.1:1935/live/test

SDL显示的API

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_CreateThread():创建一个线程

• SDL_LockMutex(), SDL_UnlockMutex():互斥量操作

• 数据结构

• SDL_Thread:线程的句柄

SDL事件

• 函数

• SDL_WaitEvent():等待一个事件

• SDL_PushEvent():发送一个事件

• SDL_PumpEvents():将硬件设备产生的事件放入事件队列

• SDL_PeepEvents():从事件队列提取一个事件

• 数据结构

• SDL_Event:代表一个事件

ffmpeg的API

参考:FFmpeg架构全面分析 - Coder个人博客 - 博客园 (cnblogs.com)

整体框架

​ 1、AVUtil: 核心工具库,许多其他模块都会依赖该库做一些基本的音视频处理操作,如log信息、版本信息等。

2、AVFormat: 文件格式和协议库,封装了Protocol层和Demuxer、Muxer层。其中实现了目前多媒体领域中的绝大多数媒体封装格式,包括封装和解封装,如MP4、FLV、KV、TS等文件封装格式,RTMP、RTSP、MMS、HLS等网络协议封装格式。FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行媒体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块。

3、AVCodec: 编解码库,封装了Codec库,AVCodec中实现了目前多媒体领域绝大多数常用的编解码格式,即支持编码,也支持解码。AVCodec除了支持MPEG4、AAC、MJPEG等自带的媒体编解码格式之外,还支持第三方的编解码器,如H.264(AVC)编码,需要使用x264编码器;H.265(HEVC)编码,需要使用x264编码器;MP3(mp3lame)编码,需要使用libmp3lame编码器。如果希望增加自己的编码格式,或者硬件编解码,则需要在AVCodec中增加相应的编解码模块。默认不会添加libx264、libfdk_aac等三方库的,但可以插件形式添加,然后提供统一接口。

4、AVFilter: 提供了一个通用的音频、视频、字幕等滤镜处理框架。在AVFilter中,滤镜框架可以有多个输入和多个输出。

5、AVDevice: 输入输出设备库,音/视频的输入输出需要确保该模块已经打开

6、SwrResample: 该模块可用于音频重采样,可以对数字音频进行声道数、数据格式、采样率、等多种基本信息的转换,同时支持音频通道布局转换与布局调整。

7、SWScale: 提供了高级别的图像转换API,例如它允许进行图像缩放和像素格式转换,常见于将图像从1080p转换成720p或者480p等的缩放,或者将图像数据从YUV420p转换成YUYV,或者YUV转RGB等图像格式转换。

8、PostProc: 该模块可用于进行后期处理,当我们使用AVFilter的时 候需要打开该模块的开关,因为Filter中会使用到该模块的一些基础函数。

结构体以及关系

重要结构体

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

​ • iformat:输入媒体的AVInputFormat,比如指向AVInputFormat ff_flv_demuxer

​ • nb_streams:输入媒体的AVStream 个数

​ • streams:输入媒体的AVStream []数组

​ • duration:输入媒体的时长(以微秒为单位),计算方式可以参考av_dump_format()函数。

​ • bit_rate:输入媒体的码率

AVCodecContext 编码器上下文结构体

​ • codec:编解码器的AVCodec,比如指向AVCodec ff_aac_latm_decoder

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

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

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

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

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

AVCodecParameters 用于存储编码流的属性。在新版本中被设计来替代已废弃的 AVCodecContext

• codectype:编解码器类型,取值为AVMEDIATYPEVIDEO、AVMEDIATYPEAUDIO、 AVMEDIATYPE_SUBTITLE之一。

• codec_id:编解码器的ID,取值为枚举类型AVCodecID中的一种。

• codec_tag:编解码器标签。

• extradata:对于某些编码器(如H.264)需要额外的信息来解码,这些信息称为"extradata"。该成员变量保存了这些额外信息的地址。

• extradata_size:extradata所占用的字节数。

• format:音视频帧的像素或采样格式,例如对于视频来说,可以是AVPIXFMTYUV420P、AVPIXFMTNV12等等。对于音频来说,可以是AVSAMPLEFMTS16、AVSAMPLEFMTFLTP等等。

• bit_rate:比特率,用于描述音视频流的质量,单位为bps。

• bitspercoded_sample:每个编码的样本所占用的位数。

• bitsperraw_sample:每个采样的样本所占用的位数。

• profile:编解码器的协议等级。

• level:编解码器的协议等级。

• width:视频帧宽度。

• height:视频帧高度。

• sample_rate:音频采样率。

• channels:音频声道数。

• samplefmt:音频采样格式,例如AVSAMPLEFMTS16、AVSAMPLEFMT_FLTP等等。

• channellayout:音频声道布局,例如AVCHLAYOUTMONO、AVCHLAYOUT_STEREO等等。

• sampleaspectratio:音视频帧宽高比。

• fpsfirstnum:帧率分子。

• fpssecondnum:帧率分母。

• delay:编码器的编码时延。

• seek_preroll:如果需要进行关键帧的跳转,这个字段表示需要跳过的帧数。

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

​ • index:标识该视频/音频流

​ • id:流的ID,用于在文件格式中识别流。

​ • time_base:该流的时基, PTS*time_base=真正的时间(秒)

​ • avg_frame_rate: 该流的帧率

​ • duration:该视频/音频流长度

​ • codecpar:编解码器参数属性

AVPacket 存储一帧压缩编码数据

​ • pts:显示时间戳

​ • dts:解码时间戳

​ • data:压缩编码数据

​ • size:压缩编码数据大小

​ • pos:数据的偏移地址

​ • stream_index:所属的AVStream

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

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

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

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

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

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

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

​ • nb_samples:音频每通道采样数(只针对音频)

​ • pts:显示时间戳

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

​ • name:编解码器名称

​ • type:编解码器类型

​ • id:编解码器ID

​ • 一些编解码的接口函数,比如int (*decode)()

AVOutputFormatAVInputFormat ffmpeg内部使用

​ • name:封装格式名称

​ • extensions:封装格式的扩展名

​ • id:封装格式ID

​ • 一些封装格式处理的接口函数,比如read_packet()

AVCodecParameters

​ • codec_type:媒体类型,比如AVMEDIA_TYPE_VIDEO AVMEDIA_TYPE_AUDIO等

​ • codec_id:编解码器类型, 比如AV_CODEC_ID_H264 AV_CODEC_ID_AAC等。

AVDictionary

简单的key/value存储,经常使用AVDictionary设置或读取内部参数。声明如下,具体实现在libavutil模块中的dict.c/h,提供此结构体是为了与libav兼容,但它实现效率低下,在FFmpeg 4.1.3版本中已弃用(deprecated),推荐使用libavutil模块中的tree.c/h来替代

AVDictionary* dict = nullptr;

av_dict_set(&dict, "max_delay", "100", 0); // 设置

很多地方需要参数的时候都会使用。也可以自行打印:

AVDictionaryEntry* t = nullptr;

while (t = av_dict_get(dict , "", t, AV_DICT_IGNORE_SUFFIX)) {

fprintf(stdout, "key: %s, value: %s\n", t->key, t->value); // iterate over all entries in d

}

av_dict_free(&dict); // 释放

AVFilter 过滤器

const char *name; // overlay

const AVFilterPad *inputs;

const AVFilterPad *outputs;

AVFilterContext 过滤器上下文

AVFilterGraph 过滤器图,对整个过滤器进行管道拼接和管理

struct AVFilterGraph

{

AVFilterContext **filters;

unsigned nb_filters;

}

AVFilterLink 两个过滤器之间的连接

struct AVFilterLink

{

AVFilterContext *src;

AVFilterPad *srcpad;

AVFilterContext *dst;

AVFilterPad *dstpad;

struct AVFilterGraph *graph;

}

重要结构体关系
  1. AVFormatContext和AVInputFormat之间的关系

    AVFormatContext API调用

    AVInputFormat 主要是FFMPEG内部调用

  2. AVCodecContext和AVCodec之间的关系

    AVCodecContext 编码器上下文结构体

    AVCodec 每种视频(音频)编解码器

  3. AVFormatContext、AVStream和AVCodecContext之间的关系

  • AVFormatContext 是最顶层的结构,代表整个多媒体文件。

  • AVStreamAVFormatContext 的一部分,代表文件中的单个媒体流。

  • AVCodecContext 是与 AVStream 相关联的,代表单个媒体流的编解码器上下文。

  1. AVPacket和AVFrame之间的关系

    AVPacket是AVFrame编码后的数据。

  2. AVFilterContext,AVFilterGraph,和AVFilter的关系:

    AVFilter是具体的各个过滤器,有不同功能。AVFilterContext是各个AVFilter的上下文,用于后期拼接,以及参数设置,管理filter与外部的联系 。AVFilterGraph是整个过滤器管理器,类似gstreamer的插件管道,用于初始化和开启过滤器。

内存模型

内部使用AVBuffer保存数据,内部有一个引用计数来保证内存正确释放。

引用计数原理:

◼ 对于多个AVPacket共享同一个缓存空间, FFmpeg使用的引用计数的机制(reference-count) :

  • 初始化引用计数为0,只有真正分配AVBuffer的时候,引用计数初始化为1;
  • 当有新的Packet引用共享的缓存空间时, 就将引用计数+1;
  • 当释放了引用共享空间的Packet,就将引用计数-1;引用计数为0时,就释放掉引用的缓存空间AVBuffer。
  • AVFrame也是采用同样的机制。

所以,从现有的Packet拷贝一个新Packet的时候,有两种情况:

• ①两个Packet的buf引用的是同一数据缓存空间,这时候要注意数据缓存空间的释放问题;

• ②两个Packet的buf引用不同的数据缓存空间,每个Packet都有数据缓存空间的copy;

AVPacket:

函数 说明
AVPacket *av_packet_alloc(void); 分配AVPacket 这个时候和buffer没有关系
void av_packet_free(AVPacket **pkt); 释放AVPacket 和_alloc对应
void av_init_packet(AVPacket *pkt); 初始化AVPacket 只是单纯初始化pkt字段
int av_new_packet(AVPacket *pkt, int size); 给AVPacket的buf分配内存, 引 用计数初始化为1
int av_packet_ref(AVPacket *dst, const AVPacket *src); 增加引用计数
void av_packet_unref(AVPacket *pkt); 减少引用计数
void av_packet_move_ref(AVPacket *dst, AVPacket *src); 转移引用计数
AVPacket av_packet_clone(const AVPacket *src); 等于 av_packet_alloc()+av_packet_ref()
int av_write_frame(AVFormatContext *s, AVPacket *pkt); 顺序写帧。将编码数据包写入到多媒体容器格式中
void av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt); 交替写帧。用于视频和音频同时存在的场景
void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt); 打印pts,dts,duration等信息

AVFrame:

函数 说明
AVFrame *av_frame_alloc(void); 分配AVFrame
void av_frame_free(AVFrame **frame); 释放AVFrame
int av_frame_ref(AVFrame *dst, const AVFrame *src); 增加引用计数
void av_frame_unref(AVFrame *frame); 减少引用计数
void av_frame_move_ref(AVFrame *dst, AVFrame *src); 转移引用计数
int av_frame_get_buffer(AVFrame *frame, int align); 根据AVFrame分配内存
AVFrame *av_frame_clone(const AVFrame *src); 等于 av_frame_alloc()+av_frame_ref()

播放器框架:

函数用处

初始化

◼ av_register_all(): 注册所有组件,4.0已经弃用

◼ avdevice_register_all()对设备进行注册,比如V4L2等

◼ avformat_network_init();初始化网络库以及网络加密协议相关的库(比如openssl)

上下文相关

◼ avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec):将AVCodecContext结构体中码流参数拷⻉到AVCodecParameters结构体中 。

封装

◼ avformat_write_header(); 写媒体头

◼ av_write_frame/av_interleaved_write_frame: 写packet

◼ av_write_trailer():写媒体尾

◼ avformat_alloc_context();负责申请一个AVFormatContext结构的内存,并进行简单初始化

◼ avformat_free_context();释放该结构里的所有东西以及该结构本身

◼ avformat_close_input();关闭解复用器。关闭后就不再需要使用avformat_free_context 进行释放。

◼ avformat_open_input();打开输入视频文件

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

◼ av_read_frame(); 读取音视频包

◼ avformat_seek_file(); 定位文件

◼ av_seek_frame():定位文件,也可以移动播放位置

编码

◼ avcodec_register_all(); 注册所有可用的编解码器和格式。

◼ avcodec_find_encoder(); 根据ID创建编码器

◼ avcodec_find_encoder_by_name(); 根据名字查找并创建编码器

◼ avcodec_alloc_context3(); 分配并初始化 AVCodecContext 结构,存储编码器或解码器的参数

◼ avcodec_open2(); 打开指定的编码器或解码器,初始化它的上下文。需要在编码或解码前调用

◼ avcodec_send_frame(); 发送frame到编码器

◼ avcodec_receive_packet(); 接收编码后的packet

◼ av_rescale_q(); 改变时间基

◼ av_image_fill_arrays(); 填充图片数据

◼ avcodec_flush_buffers(); 用于清空编码器或解码器的缓冲区。这在处理流式数据时非常有用,比如在开始处理新的视频流时,确保先前的帧数据被清除

◼ avcodec_close(); 关闭

◼ avcodec_free_context();

解码

◼ avcodec_register_all(); 注册所有可用的编解码器和格式。

◼ avcodec_find_decoder(); 根据ID创建解码器

◼ avcodec_find_decoder_by_name(); 根据名字查找并创建编码器

◼ avcodec_alloc_context3(); 分配并初始化 AVCodecContext 结构,存储编码器或解码器的参数

◼ avcodec_open2(); 打开指定的编码器或解码器,初始化它的上下文。需要在编码或解码前调用

◼ avcodec_send_packet(); 发送packet到编码器

◼ avcodec_receive_frame(); 接收编码后的frame

◼ avcodec_flush_buffers(); 用于清空编码器或解码器的缓冲区。这在处理流式数据时非常有用,比如在开始处理新的视频流时,确保先前的帧数据被清除

◼ avcodec_close(); 关闭

◼ avcodec_free_context();

音频重采样

从uint_8 *data 的音频数据,转为AVFrame * 数据。

#include "libswresample/swresample.h"

重要结构体:SwrContext

◼ swr_alloc_set_opts(SwrContext *s , ...); 根据设置的输出和输入的采样参数,创建上下文

◼ swr_convert(SwrContext *s, ...); 重采样,根据上下文,将uint8_t *音频数据转换为AVFrame.data里面去。

◼ swr_init(SwrContext ctx); 初始化

◼ swr_free(SwrContext **ss);

过滤器
//#include <libavfilter/avfiltergraph.h>
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>

◼ avfilter_register_all(); 注册过滤器

◼ avfilter_get_by_name(const char name); 根据名字创建过滤器

◼ av_buffersrc_add_frame(AVFilterContext ctx, AVFrame frame); 往源过滤器输入数据

◼ av_buffersink_get_frame(AVFilterContext ctx, AVFrame frame); 从终点过滤器中获取数据

◼ avfilter_graph_alloc(); 创建⼀个滤波器图实例 AVFilterGraph*

◼ avfilter_graph_parse2(); 根据 传递的字符串语法来创建一个或者多个滤镜上下文,多个滤镜会根据语法自动连接。同时会把新创建的滤镜上下文放进去滤镜容器。

◼ avfilter_graph_create_filter(...); 创建某个滤波器实例AVFilterContext(如果之前是空指针),设置参数并添加到AVFilterGraph中

◼ avfilter_graph_get_filter(); 根据名称获取 滤镜容器内部的某个滤镜上下文。

◼ avfilter_link(); 连接两个过滤器。从上一个过滤器的某个输出点,连接到下一个过滤器的某个输入点

◼ avfilter_graph_config(); 检查过滤器图,并且开启

◼ avfilter_graph_dump(); 将过滤器图导出txt

◼ avfilter_graph_free(); 释放内存,包括过滤器和上下文

◼ avfilter_init_str(); 使用提供的参数,初始化过滤器

相关推荐
悟空非空也19 分钟前
178K⭐排名第一计算机面试笔记
笔记·面试·职场和发展
Eshin_Ye1 小时前
transformer学习笔记-自注意力机制(1)
笔记·学习·transformer·attention·注意力机制
索然无味io2 小时前
SQL注入--Access注入
数据库·笔记·sql·学习·mysql·网络安全
Octopus20772 小时前
【Linux】git操作
linux·笔记·git·学习
从善若水2 小时前
【Rust 学习笔记】Rust 基础数据类型介绍——数组、向量和切片
笔记·学习·rust
荷逸同学2 小时前
小红书笔记采集链接版 | 同步飞书
笔记·飞书
努力学习的少女2 小时前
linux/centOS7用户和权限管理笔记
linux·运维·笔记
胡楚昊3 小时前
攻防世界安卓刷题笔记(新手模式)1-4
笔记
m0_748238423 小时前
【Vue3】前端使用 FFmpeg.wasm 完成用户视频录制,并对视频进行压缩处理
前端·ffmpeg·wasm