环境安装
QT环境安装
- 运行qt…run安装
下载地址:https://download.qt.io/archive/qt/
下载地址:https://download.qt.io/archive/qt/5.12/5.12.10/
-
sudo apt install --reinstall libxcb-xinerama0 解决xcb问题
-
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_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
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
#如果用的是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
头文件导入
//必须加以下内容,否则编译不能通过,为了兼容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)()
AVOutputFormat 和 AVInputFormat 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;
}
重要结构体关系
-
AVFormatContext和AVInputFormat之间的关系
AVFormatContext API调用
AVInputFormat 主要是FFMPEG内部调用 -
AVCodecContext和AVCodec之间的关系
AVCodecContext 编码器上下文结构体
AVCodec 每种视频(音频)编解码器
-
AVFormatContext、AVStream和AVCodecContext之间的关系
-
AVFormatContext
是最顶层的结构,代表整个多媒体文件。 -
AVStream
是AVFormatContext
的一部分,代表文件中的单个媒体流。 -
AVCodecContext
是与AVStream
相关联的,代表单个媒体流的编解码器上下文。
-
AVPacket和AVFrame之间的关系
AVPacket是AVFrame编码后的数据。
-
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(); 使用提供的参数,初始化过滤器