###音視頻基礎知識ios
####視頻播放原理git
咱們先從一個簡單的視頻播放器的原理開始講述,下圖是一個最簡單的視頻播放的過程(不包括視頻加密等等過程):算法
這是一個視頻播放的最基本的原理流程圖,從這個圖能夠很總體得看到視頻處理的一些主要步驟,後面咱們會詳細介紹一些這裏提到的基本概念。編程
######注意:咱們利用FFmpeg進行編程的時候幾乎就是基於這個流程圖來進行。好比說,編程的時候咱們會拿到解碼器,解碼讀取數據,繪製到屏幕上面的時候可能還須要把YUV數據轉換爲RGB等等。瀏覽器
咱們常見的封裝視頻的格式有:flv(音視頻分開)、mp四、avi等等。後面咱們會詳細說明。服務器
####爲何視頻須要通過封裝處理呢?微信
由於攝像頭採集到的畫面、以及麥克風採集到的音頻數據是通過壓縮的處理,否則視頻文件就會很大。數據結構
也就是說:函數
####視頻的封裝格式介紹工具
封裝格式的做用是:視頻碼流和音頻碼流按照必定的格式存儲在一個文件中。
封裝格式分析工具:Elecard Format Analyzer
爲何要音視頻分開存儲呢?由於音視頻的編碼格式各類各樣,同時編碼必然會形成混亂。
常見的視頻封裝格式有:
以兩個格式爲例子,介紹一下原理:
####視頻編解碼常見格式介紹
視頻的壓縮算法不少,所以編碼格式就會有不少種,下面介紹一些常見的編解碼格式:
#####視頻編解碼格式:
原理分析:
以H264爲例,H264是由大小不固定的NALU構成。(NALU實質是一種數據結構)。H264裏面有不少子壓縮算法,原理比較複雜,包括了熵編碼,環路濾波,幀內檢測,幀間檢測等知識。H264編碼原理比較複雜,所以H264的壓縮效率是幾百到幾千倍。
######咱們須要學會FFmpeg便可,由於這個庫封裝了H264等格式的處理。
視頻解碼(攝像機獲取)獲得的是視頻像素數據,保存了屏幕上每一個像素點的像素值。常見的像素數據格式有RGB24, RGB32, YUV420P,YUV422P,YUV444P等。壓縮編碼中通常使用的是YUV格式的像素數據,最爲常見的格式爲YUV420P。
YUV視頻格式是沒有通過壓縮的,很大。早期在電視上面用得比較多,好比古老的黑白、彩電。彩電播放早期的黑白視頻實質上是隻播放了Y(亮度)的數據,由於黑白視頻只有Y的數據嘛。
RGB也有不少種,好比RGB24,不一樣的RGB編碼色彩豐富度不一樣。
#####音視頻編解碼格式:
######在作視頻直播的時候:音頻經常使用AAC來進行編碼,用FAAC庫來處理;視頻用H264編碼。
音頻採樣數據PCM:保存了音頻中每一個採樣點的值,音頻採樣數據體積很大,通常須要進過壓縮,咱們日常說的「無損」實質上是沒有損失的壓縮的意思。
#####相關播放(編輯)工具
有興趣能夠下載玩玩。
###FFmpeg介紹
FFmpeg是開源的C/C++音視頻處理的類庫,這個庫十分優秀,以致於不少大公司都在用。主流的視頻播放器幾乎都使用了FFmpeg。
####FFmpeg的八個函數庫的基本介紹
以下圖所示:
###Visual Studio下FFmpeg的項目配置
####前言
咱們通常是在VS中寫好代碼而後放到Android中的,所以有必要搭建VS的開發環境。
####FFmpeg資源獲取
首先咱們須要去FFmpeg的官網去獲取源碼,由於獲取的步驟比較麻煩,固下個筆記記錄下來,咱們打開ffmpeg.org/:
點擊官網中大大的Download按鈕,跳轉到下面的界面:
選擇對應的系統,這裏咱們先介紹Windows版本的,點擊下面的Windows Builds,跳轉到下面的界面:
咱們推薦使用舊版的FFmpeg庫,由於若是使用新版的話,除了問題很難去百度。筆者的電腦是64位的,因而就點擊All 64-bit Downloads。而後咱們會跳轉到下面這個倉庫頁面:
其中,咱們須要下載的FFmpeg版本是2.8系列的,咱們推薦使用2.8或者如下的版本。其中,dev是開發版本的庫,shared是一些動態連接庫,static是一些已經編譯好的exe(Windows版本)可執行文件。這三個咱們都須要下載下來。
若是你嫌麻煩的話,我下面直接給出下載地址:
https://ffmpeg.zeranoe.com/builds/win64/dev/2015/ffmpeg-20151105-git-c878082-win64-dev.7z
https://ffmpeg.zeranoe.com/builds/win64/shared/2015/ffmpeg-20151105-git-c878082-win64-shared.7z
https://ffmpeg.zeranoe.com/builds/win64/static/2015/ffmpeg-20151105-git-c878082-win64-static.7z
下面並解壓的效果以下:
注意:下面分別用dev、static、shared來表明這三個文件夾。
####在命令行玩一玩static中的可執行文件
咱們打開static文件夾,裏面有個bin目錄,有三個exe文件。這就是咱們即將要玩的東西:
爲了簡化操做,咱們不妨把bin目錄添加到環境變量path中。
而後咱們準備一個測試用的視頻,例如筆者準備了一個test.flv視頻文件。
打開命令行,輸入:
ffmpeg -i test.flv test.avi
複製代碼
而後這就完成了一次簡單的視頻格式轉換。相信細心的你也會發現,FFmpeg的官網上面有這麼一幅圖:
其實這就是一個最簡單的例子。
下面咱們再來搞一個是視頻轉GIF,在命令行輸入下面的語句:
ffmpeg -ss 0 -t 11 -i test.flv -s 1366x768 -b:v 1500k test.gif
複製代碼
意思就是把test.flv轉換爲test.gif文件,其中須要指定轉換的時間範圍,分辨率大小,比特率。
######碼率(比特率),單位時間每一幀畫面以及音頻的大小,也叫做比特每秒,單位時間內播放連續的媒體例如壓縮後的音頻或者視頻的比特數量。碼率越高,音視頻越清晰。
######把視頻轉gif是頗有意義的,例如微信中的小視頻,咱們沒有點開的時候,其實播放的是一個gif文件(可能使用的是libgif這個NDK庫),用戶點擊打開的時候,纔會從服務器下載真正的視頻文件。這樣作大大下降了服務器的壓力。
最後咱們看一個播放器的例子,輸入下面的命令,就會打開一個播放器,因此說若是你想研究一個Android平臺的播放器,那麼須要研究ffplay相關的代碼:
ffplay test.flv
複製代碼
####FFmpeg的VS項目配置
咱們首先建立一個空項目,而後把dev中的include、lib兩個目錄拷貝到項目的根路徑下的源代碼目錄中(默認是與項目名同樣)。
而後在項目屬性中配置附加庫目錄:
而後配置附加庫目錄:
而後配置有哪些附加庫(附加依賴項),以下面所示:
avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib
swscale.lib
複製代碼
最後咱們建立一個測試用的CPP文件:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
//因爲FFmpeg是C和C++混編的,所以使用extern是爲了解決兼容問題
extern "C"{
#include "libavcodec/avcodec.h"
}
void main(){
//輸出FFmpeg的配置信息,檢查是否配置好
cout << avcodec_configuration() << endl;
system("pause");
}
複製代碼
而後你會發現編譯不過,由於咱們用的FFmpeg庫是64位的,所以須要把咱們的平臺改成64位的:
而後編譯經過,輸出的結果以下:
#####題外話——關於extern關鍵字的基本解釋
extern能夠置於變量或者函數前,以標示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其餘模塊中尋找其定義。此外extern也可用來進行連接指定。也就是說extern有兩個做用:
若是以爲個人文字對你有所幫助的話,歡迎關注個人公衆號:
個人羣歡迎你們進來探討各類技術與非技術的話題,有興趣的朋友們加我私人微信huannan88,我拉你進羣交(♂)流(♀)。