[TOC]
# 簡介
FFMPEG是特別強大的專門用于處理音視頻的開源庫。你既可以使用它的API對音視頻進行處理,也可以使用它提供的工具,如 ffmpeg, ffplay, ffprobe,來編輯你的音視頻文件。
# 目錄以及作用
* libavcodec: 提供了一系列編碼器的實現。
* libavformat: 實現在流協議,容器格式及其本IO訪問。
* libavutil: 包括了hash器,解碼器和各利工具函數。
* libavfilter: 提供了各種音視頻過濾器。
* libavdevice: 提供了訪問捕獲設備和回放設備的接口。
* libswresample: 實現了混音和重采樣。
* libswscale: 實現了色彩轉換和縮放工能
# 基本概念
* 音/視頻流
在音視頻領域,我們把一路音/視頻稱為一路**流**。如我們小時候經常使用VCD看港片,在里邊可以選擇粵語或國語聲音,其實就是CD視頻文件中存放了兩路音頻流,用戶可以選擇其中一路進行播放。
* 容器
我們一般把 MP4? FLV、MOV等文件格式稱之為**容器**。也就是在這些常用格式文件中,可以存放多路音視頻文件。以 MP4 為例,就可以存放一路視頻流,多路音頻流,多路字幕流。
* channel
channel是音頻中的概念,稱之為聲道。在一路音頻流中,可以有單聲道,雙聲道或立體聲。
# 播放器架構

# 渲染過程

# ffmpeg處理音視流程

將編碼的數據包傳送給解碼器(除非為數據流選擇了流拷貝)。
解碼器產生未壓縮的幀(原始視頻/ PCM音頻/ ...),可以通過濾波進一步處理。
在過濾之后,幀被傳遞到編碼器,編碼器并輸出編碼的數據包。 最后,這些傳遞給復用器,將編碼的數據包寫入輸出文件。
默認情況下,ffmpeg只包含輸入文件中每種類型(視頻,音頻,字幕)的一個流,并將其添加到每個輸出文件中。 它根據以下標準挑選每一個的“最佳”:對于視頻,它是具有最高分辨率的流,對于音頻,它是具有最多channel的流,對于字幕,是第一個字幕流。 在相同類型的幾個流相等的情況下,選擇具有最低索引的流。
您可以通過使用`-vn/-an/-sn/-dn`選項來禁用某些默認設置。 要進行全面的手動控制,請使用`-map`選項,該選項禁用剛描述的默認設置
# 下載編譯與安裝
**mac需要這個才能錄制聲音**
~~~
brew cask install soundflower
~~~
還要配置下的去常見錯誤那看
**下載編譯**
~~~
git clone https://git.ffmpeg.org/ffmpeg.git
./configure --help
~~~

缺少的要去安裝
~~~
make && make install
~~~
這些安裝包的版本都是Homebrew的方案(formulas),安裝程序會自動將FFmpeg的依賴庫安裝好。你可以輸入`brew info ffmpeg`查看額外的安裝選項,如:如果想要添加`libfdk_aac`或`libvpx`兩個庫(這兩個庫是高度推薦安裝的),可以輸入以下包含額外推薦選項的命令:
~~~
brew install ffmpeg --with-fdk-aac --with-ffplay --with-freetype --with-libass --with-libquvi --with-libvorbis --with-libvpx --with-opus --with-x265
~~~
如果你想通過Homebrew安裝FFmpeg的最新Git版本,在第一條安裝命令后面添加`--HEAD`,如:
~~~
brew install ffmpeg --HEAD
~~~
或者
~~~
brew install ffmpeg --with-chromaprint --with-fdk-aac --with-libass --with-libsoxr --with-libssh --with-tesseract --with-libvidstab --with-opencore-amr --with-openh264 --with-openjpeg --with-openssl --with-rtmpdump --with-rubberband --with-sdl2 --with-snappy --with-tools --with-webp --with-x265 --with-xz --with-zeromq --with-zimg --with-fontconfig --with-freetype --with-frei0r --with-game-music-emu --with-libbluray --with-libbs2b --with-libcaca --with-libgsm --with-libmodplug --with-libvorbis --with-libvpx --with-opus --with-speex --with-theora --with-two-lame --with-wavpack
~~~
**如果需要'libfdk_aac'可以**
~~~
brew install fdk-aac
~~~
或者
~~~
git clone git://github.com/mstorsjo/fdk-aac
cd fdk-aac
autoreconf -i
./configure
make install
~~~
或者
~~~
brew install ffmpeg --with-fdk-aac
~~~
**mac編譯需要這些**
~~~
brew install automake fdk-aac git lam libass libtool libvorbis libvpx \ opus sdl shtool texi2html theora wget x264 xvid yasm
~~~
在執行各自的 configure 創建編譯配置文件時,最好都強制帶上 --enable-static 和 --enable-shared 參數以確保生成靜態庫和動態庫。另外因為是在 Mac OS X 環境下編譯,因此在各自編譯完后,都要執行 sudo make install,安裝到默認的 `/usr/local` 目錄下相應位置(Mac OS X 下不推薦 /usr),因此不要在 configure 時指定 --prefix,就用默認的 /usr/local 目錄前綴即可。完成編譯安裝后,FFmpeg 的頭文件將會復制到 /usr/local/include 下面相應位置,靜態庫及動態庫會被復制到 `/usr/local/lib` 目錄下,FFmpeg 的可執行程序(ffmpeg、ffprobe、ffserver)會被復制到 `/usr/local/bin` 目錄下,這樣 FFmpeg 的開發環境就構建好了
# 聲音
* 音調: 就是音頻, 男生->女生->兒童
* 音量: 振動的幅度
* 音色: 它與材質有很大的關系,本質是諧波
聲波波形圖

音色

聽覺范圍

模擬信號轉數字信號
音頻量化過程

**量化基本概念**
* 采樣大小: 一個采樣用多少bit存放.常用的是16bit
* 采樣率: 采樣率8k, 16k, 32k, 44.1k, 48k
* 聲道數: 單聲道,雙聲道,多聲道
**碼率計算**
要計算一個PCM音頻流的碼率是一件很輕松的事情,`采樣率*采樣大小*聲道數`
例如 : 采樣率為44.1KHz,采樣大小為16bit,雙聲道的PCM編碼的WAV文件,它的碼率為`44.1k*16*2=1411.2kb/s`
## 音頻壓縮
* 消除冗余數據
* 哈夫曼無損編碼
## 音頻的冗余信息
* 壓縮的主要方法是去除采集到的音頻冗余信息,所謂冗余信息包括人耳聽覺范圍外的音頻信號以及被掩蔽掉的音頻信號
* 信號的掩蔽可以分為頻域掩蔽和時域掩蔽
## 音頻編碼過程

## 常見的音頻編碼器
* 常見的音頻編碼器包括OPUS,AAC,Vorbis,Speex,iLBC,AMR,G.711等
OPUS>AAC>Vorbis
**AAC規格**
* `AAC LC`: 低復雜度,碼流128k
* `AAC HE`: `AAC LC + SBR(分屏復用)`
* `AAC HE V2`: `AAC LC + SBR + PS(雙聲道)`
**AAC格式**
* ADIF這種格式只能從頭開始解碼,常用在磁盤文件中
* ADTS這種格式每一幀都有一個同步字,可以在音頻流的任何位置開始解碼,它類似于數據流格式
AAC編碼庫那個好?
`Libfdk_AAC` > `ffmpeg AAC` > `libfaac` > `libvo_aacenc`
# 視頻
**H264基本概念**
* I幀: 關鍵幀,采用幀內壓縮技術
* P幀: 向前參考幀,壓縮時只參考前一個幀,屬于幀間壓縮技術
* B幀: 雙向參考幀,壓縮時即參考前一幀也參考后一幀,幀間壓縮技術
**GOF**
一組幀,一個I幀和另一個I幀,或者一個P幀和另一個P幀

**SPS與PPS**
* SPS: 序列參數集,存放幀數,參考幀數目,解碼圖像尺寸,幀場編碼模式選擇標識等
* PPS: 圖像參數集,存放熵編碼模式選擇標識,片組數目,初始化量化參數和去方法濾波系數調整標識等
## 視頻花屏卡頓原因
* 如果GOP分組中的P幀丟失會造成解碼端的圖像發生錯誤
* 為了避免花屏問題的發生,一般如果發現P幀或者I幀丟失,就不顯示本GOP內的所有幀,直到下一個I幀來后重新刷新圖像
花屏是丟了數據
卡頓是為了不花屏把那一組數據丟了
## 常見哪些視頻編碼器
* `x264/x265`
* openH264
* vp8/vp9
**H264壓縮技術**
* 幀內預測壓縮,解決的是空域數據冗余問題
* 幀間預測壓縮,解決的是時域數據冗余問題
* 整數離散余弦變換(DCT),將空間上的相關性變為頻域上無關的數據然后進行量化
* CABAC壓縮,無損壓縮
**宏塊劃分與分組**
H264宏塊劃分


**子塊劃分**

**幀分組**

## 視頻壓縮
**組內宏塊查找**

**運動估算**

**運動矢量與補償壓縮**

**幀內預測**

計算幀內預測殘差值
**DCT壓縮**
**vlc壓縮**
**CABAC壓縮**

## H264結構圖

## H264編碼分層
* NAL層: 視頻數據網絡抽象層
* VCL層: 視頻數據編碼層
**碼流基本概念**
* SODB: 原始數據比特流,長度不一定是8的倍數,他是由vcl層產生的
* RBSP: 算法是SODB最后一位補1,不按字節對齊則補0
* EBSP: 需到兩個連續的0x00就增加一個0x03
* NALU: `NAL Header(1B)+EBSP`
**切片和宏塊的關系**

**H264切片**

## YUV
**圖像除了RGB還有YUV**
* YUV是電視系統采用的一種顏色編碼方法
* Y表示明亮度,也就是灰階值,它是基礎信號
* U和V表示的則是色度,UV是作用是描述影響色彩以及飽和度,它們用于指定像素的顏色
**常見格式**
* YUV4:2:0 (YCbCr 4:2:0)
* YUV4:2:2(YCbcR 4:2:2)
* YUV4:4:4 (YCbCr 4:4:4)
**YUV存儲格式**
* planar(平面)
* packed(打包)
李老師,你好,我在ubuntu上用FFmpeg推流本地視頻的時候到rtmp的時候(ffmpeg -re -i test2.mp4 -c copy -f flv rtmp://172.16.202.128:1935/live/room),出現了這個錯誤:
[flv @ 0x555c87c208c0] Video codec hevc not compatible with flv
Could not write header for output file #0 (incorrect codec parameters ?): Function not implemented
Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #0:1 -> #0:1 (copy) Last message repeated 1 times
但是,當我把MP4轉換成flv格式之后,就可以推流拉流,進行播放了
你的mp4文件使用的視頻格式是 hevc, 這個太新了,由于flv 已經不更新了,所以不能在 flv文件中寫入 hevc格式的視頻。你轉成? flv文件之所以可以推流是因為在轉格式的時候 視頻格式也發生了變化,就成了flv可以支持的視頻格式,所以才能推流成功
- c語言
- 基礎知識
- 變量和常量
- 宏定義和預處理
- 隨機數
- register變量
- errno全局變量
- 靜態變量
- 類型
- 數組
- 類型轉換
- vs中c4996錯誤
- 數據類型和長度
- 二進制數,八進制數和十六進制數
- 位域
- typedef定義類型
- 函數和編譯
- 函數調用慣例
- 函數進棧和出棧
- 函數
- 編譯
- sizeof
- main函數接收參數
- 宏函數
- 目標文件和可執行文件有什么
- 強符號和弱符號
- 什么是鏈接
- 符號
- 強引用和弱引用
- 字符串處理函數
- sscanf
- 查找子字符串
- 字符串指針
- qt
- MFC
- 指針
- 簡介
- 指針詳解
- 案例
- 指針數組
- 偏移量
- 間接賦值
- 易錯點
- 二級指針
- 結構體指針
- 字節對齊
- 函數指針
- 指針例子
- main接收用戶輸入
- 內存布局
- 內存分區
- 空間開辟和釋放
- 堆空間操作字符串
- 內存處理函數
- 內存分頁
- 內存模型
- 棧
- 棧溢出攻擊
- 內存泄露
- 大小端存儲法
- 寄存器
- 結構體
- 共用體
- 枚舉
- 文件操作
- 文件到底是什么
- 文件打開和關閉
- 文件的順序讀寫
- 文件的隨機讀寫
- 文件復制
- FILE和緩沖區
- 文件大小
- 插入,刪除,更改文件內容
- typeid
- 內部鏈接和外部鏈接
- 動態庫
- 調試器
- 調試的概念
- vs調試
- 多文件編程
- extern關鍵字
- 頭文件規范
- 標準庫以及標準頭文件
- 頭文件只包含一次
- static
- 多線程
- 簡介
- 創建線程threads.h
- 創建線程pthread
- gdb
- 簡介
- mac使用gdb
- setjump和longjump
- 零拷貝
- gc
- 調試器原理
- c++
- c++簡介
- c++對c的擴展
- ::作用域運算符
- 名字控制
- cpp對c的增強
- const
- 變量定義數組
- 盡量以const替換#define
- 引用
- 內聯函數
- 函數默認參數
- 函數占位參數
- 函數重載
- extern "C"
- 類和對象
- 類封裝
- 構造和析構
- 深淺拷貝
- explicit關鍵字
- 動態對象創建
- 靜態成員
- 對象模型
- this
- 友元
- 單例
- 繼承
- 多態
- 運算符重載
- 賦值重載
- 指針運算符(*,->)重載
- 前置和后置++
- 左移<<運算符重載
- 函數調用符重載
- 總結
- bool重載
- 模板
- 簡介
- 普通函數和模板函數調用
- 模板的局限性
- 類模板
- 復數的模板類
- 類模板作為參數
- 類模板繼承
- 類模板類內和類外實現
- 類模板和友元函數
- 類模板實現數組
- 類型轉換
- 異常
- 異常基本語法
- 異常的接口聲明
- 異常的棧解旋
- 異常的多態
- 標準異常庫
- 自定義異常
- io
- 流的概念和類庫結構
- 標準io流
- 標準輸入流
- 標準輸出流
- 文件讀寫
- STL
- 簡介
- string容器
- vector容器
- deque容器
- stack容器
- queue容器
- list容器
- set/multiset容器
- map/multimap容器
- pair對組
- 深淺拷貝問題
- 使用時機
- 常用算法
- 函數對象
- 謂詞
- 內建函數對象
- 函數對象適配器
- 空間適配器
- 常用遍歷算法
- 查找算法
- 排序算法
- 拷貝和替換算法
- 算術生成算法
- 集合算法
- gcc
- GDB
- makefile
- visualstudio
- VisualAssistX
- 各種插件
- utf8編碼
- 制作安裝項目
- 編譯模式
- 內存對齊
- 快捷鍵
- 自動補全
- 查看c++類內存布局
- FFmpeg
- ffmpeg架構
- 命令的基本格式
- 分解與復用
- 處理原始數據
- 錄屏和音
- 濾鏡
- 水印
- 音視頻的拼接與裁剪
- 視頻圖片轉換
- 直播
- ffplay
- 常見問題
- 多媒體文件處理
- ffmpeg代碼結構
- 日志系統
- 處理流數據
- linux
- 系統調用
- 常用IO函數
- 文件操作函數
- 文件描述符復制
- 目錄相關操作
- 時間相關函數
- 進程
- valgrind
- 進程通信
- 信號
- 信號產生函數
- 信號集
- 信號捕捉
- SIGCHLD信號
- 不可重入函數和可重入函數
- 進程組
- 會話
- 守護進程
- 線程
- 線程屬性
- 互斥鎖
- 讀寫鎖
- 條件變量
- 信號量
- 網絡
- 分層模型
- 協議格式
- TCP協議
- socket
- socket概念
- 網絡字節序
- ip地址轉換函數
- sockaddr數據結構
- 網絡套接字函數
- socket模型創建流程圖
- socket函數
- bind函數
- listen函數
- accept函數
- connect函數
- C/S模型-TCP
- 出錯處理封裝函數
- 多進程并發服務器
- 多線程并發服務器
- 多路I/O復用服務器
- select
- poll
- epoll
- epoll事件
- epoll例子
- epoll反應堆思想
- udp
- socket IPC(本地套接字domain)
- 其他常用函數
- libevent
- libevent簡介