FFmpeg的C++封裝:FFmpegWrapper

來源:互聯網
上載者:User

下面介紹的API已淘汰,請下載最新版本的原始碼,並參考其注釋。新版本主要由John編寫,在舊版本的基礎上做了很多改進。

什麼是FFmpeg?

FFmpeg是一套完整的錄製、轉換、流化音視頻的解決方案,也是一個在LGPL協議下的開源項目。它包含了業界領先的音視頻編解碼庫。FFmpeg是在Linux作業系統下開發的,但它也能在其他動作系統下編譯,包括Windows。

整個項目由以下幾個部分組成:

  • ffmpeg:一個用來轉換視頻檔案格式的命令列工具,它也支援從電視卡中即時的抓取和編碼視頻。
  • ffserver:一個基於HTTP協議(基於RTSP的版本正在開發中)用於即時廣播的多媒體伺服器,它也支援即時廣播的時間平移。
  • ffplay:一個用SDL和FFmpeg庫開發的簡單的媒體播放器。
  • libavcodec:一個包含了所有FFmpeg音視頻轉碼器的庫。為了保證最優的效能和高可複用性,大多數轉碼器都是從頭開發的。
  • libavformat:一個包含了所有的普通音視頻格式的解析器和產生器的庫。

FFmpegWrapper僅使用了libavcodec和libavformat這兩部分。

什麼是FFmpegWrapper?

FFmpegWrapper:

  • 是一個在Windows下用VS2005編寫的C++ Win32動態庫。
  • 用物件導向的方法封裝了FFmpeg庫中常用的API,使之便於使用,不需要開發人員瞭解很多音視頻編解碼的知識。
  • 其中99%的代碼符合C++標準,很容易移植到其他平台。
  • 由farthinker開發和維護。

為什麼要使用FFmpegWrapper?

對於一個對視頻編解碼不太瞭解的開發人員來說,用FFmpeg的庫來編寫應用絕對是一件痛苦的事情。首先需要編譯從SVN下載的原始碼(FFmpeg官方只提供原始碼……)。如果是在Windows下編譯,麻煩就開始了(當然你也可以直接使用別人編譯好的SDK,跳過這一步)。當你好不容易編譯好一個可以使用的動態庫之後,你會發現很難找到合適的文檔來學習如何使用FFmpeg的庫,你只能一邊參考範例程式碼一邊摸索使用方法。然後你會發現問題一個接一個的出現,你又不知從何處下手來解決。總之,使用FFmpeg的學習成本是很高的。

FFmpegWrapper的目的就在於讓FFmpeg的調用過程簡單化、物件導向化,降低使用FFmpeg的學習成本,讓對視頻編解碼不太瞭解的開發人員也能輕鬆的使用FFmpeg。但是,簡化使用的同時也在一定程度上簡化了功能,FFmpegWrapper很難繼承FFmpeg庫的所有功能。所以FFmpegWrapper適合一些編解碼需求相對簡單的應用,而不適合那些需求複雜靈活、擴充性很強的應用。

如何使用FFmpegWrapper來編解碼音視頻?

準備工作

首先下載FFmpegWrapper的庫檔案(若是在非Windows平台下使用,則需要下載原始碼自己編譯),然後將FFmpegWrapper部署到項目中。部署的過程中需要注意的是,最好不要改變ffmpeg檔案夾相對於FFmpegWrapper.h的路徑,若必須要改變,組需要修改FFmpegWrapper.h中#include “ffmpeg/include/avformat.h”的路徑。調用動態庫的具體方法這裡就不贅述了。

使用FFmpegWrapper編碼音視頻

指定音視頻參數

首先需要指定一些音視頻的參數。FFmpegWrapper中用FFmpegVideoParam和FFmpegAudioParam這兩個類來表示音視頻的參數。下面的例子指定了一個flv視頻的參數:

//指定視頻參數,從左至右分別是:寬、高、像素格式、位元速率、幀率FFmpegVideoParam videoParam(352, 288, PIX_FMT_YUV420P, 400000, 25);//指定視頻參數,從左至右分別是:位元速率、採樣率、聲道數FFmpegAudioParam audioParam(64000, 44100, 2);

若視頻中沒有視頻流(音頻流),則可以初始化一個空的FFmpegVideoParam(FFmpegAudioParam):

FFmpegVideoParam videoParam(352, 288, PIX_FMT_YUV420P, 400000, 25);//沒有音頻流,初始化一個空的音頻參數對象FFmpegAudioParam audioParam();

初始化FFmpegEncoder對象

用音視頻參數初始化FFmpegEncoder對象:

FFmpegVideoParam videoParam(352, 288, PIX_FMT_YUV420P, 400000, 25);FFmpegAudioParam audioParam(64000, 44100, 2);//參數從左至右分別是:FFmpegVideoParam、FFmpegAudioParam 、編碼輸出檔案名FFmpegEncoder testEncoder(videoParam, audioParam, "test.flv");

其中第三個參數包含了輸出檔案的路徑、名字和尾碼,並且是可選的參數,也就是說可以沒有輸出檔案。但是在沒有輸出檔案的時候需要音視頻參數中指定codec的名稱,因為FFmpegEncoder不能從檔案尾碼判斷出使用什麼codec:

FFmpegVideoParam videoParam(352, 288, PIX_FMT_YUV420P, 400000, 25,"flv");FFmpegAudioParam audioParam(64000, 44100, 2, "libmp3lame");//參數從左至右分別是:FFmpegVideoParam、FFmpegAudioParam 、編碼輸出檔案名FFmpegEncoder testEncoder(videoParam, audioParam);

逐幀編碼音視頻

開始編碼之前還需要先調用FFmpegEncoder對象的open方法,開啟相應的codec和輸出檔案:

FFmpegVideoParam videoParam(352, 288, PIX_FMT_YUV420P, 400000, 25);FFmpegAudioParam audioParam(64000, 44100, 2);FFmpegEncoder testEncoder(videoParam, audioParam,"test.flv");testEncoder.open();

然後就可以調用FFmpegEncoder對象的writeVideoFrame(writeAudioFrame)方法來逐幀的編碼並輸出視(音)頻了:

//其中videoFrameData是uint8_t *(unsigned char *)類型的參數testEncoder.writeVideoFrame(videoFrameData);//其中audioFrameData是short *類型的參數testEncoder.writeAudioFrame(audioFrameData);

如果編碼之後不需要輸出,即沒有輸出檔案,則使用encodeVideoFrame和getVideoBuffer(encodeAudioFrame和getAudioBuffer)方法來編碼和獲得編碼後的資料:

//其中videoFrameData是uint8_t *(unsigned char *)類型的參數testEncoder.encodeVideoFrame(videoFrameData);uint8_t *encodedVideo = testEncoder.getVideoBuffer();//其中audioFrameData是short *類型的參數testEncoder.encodeAudioFrame(audioFrameData);uint8_t *encodedAudio = testEncoder.getAudioBuffer();

編碼的過程中,還可以獲得音視頻的時間戳記(pts)來處理音視頻同步(暫不適用於沒有輸出檔案的情況),下面是一個例子:

short *audioData;uint8_t *videoData;double videoPts, audioPts;videoPts = testEncoder.getVideoPts();audioPts = testEncoder.getAudioPts();/* output 5 seconds test video file */while (audioPts < 5) {if (audioPts <= videoPts) {audioData = getTestAudioData();testEncoder.writeAudioFrame(audioData);} else {videoData = getVideoFrame();testEncoder.writeVideoFrame(videoData);}audioPts = testEncoder.getAudioPts();videoPts = testEncoder.getVideoPts();}

完成編碼後還需要調用FFmpegEncoder對象的close方法,關閉codec和輸出檔案並釋放資源:

testEncoder.close();

使用FFmpegWrapper解碼音視頻

初始化FFmpegDecoder對象

首先初始化一個FFmpegDecoder對象,並傳入輸入檔案的名稱(包括路徑、名字和尾碼):

FFmpegDecoder testDecoder("test.flv");

逐幀解碼音視頻開始解碼之前還需要先調用FFmpegDecoder對象的open方法,開啟相應的codec和輸入檔案:
FFmpegDecoder testDecoder("test.flv");testDecoder.open();

然後就可以調用FFmpegDecoder對象的decodeFrame方法來逐幀的解碼音視頻檔案了:

//decodeFrame的傳回值表示當前解碼的幀的狀態:// 0 - 視訊框架// 1 - 音訊框架// -1 - 檔案末尾或解碼出錯int signal = testDecoder.decodeFrame()

解碼之後可以通過FFmpegDecoder對象的getVideoFrame(getAudioFrame)方法來獲得解碼後的視(音)頻資料,下面是一個完整的例子:

int signal;uint8_t *decodedVideo;short *decodedAudio;FFmpegDecoder testDecoder("test.flv");ffencoder.open();while (true) {signal = testDecoder.decodeFrame();if (signal == 0) {decodedVideo = ffdecoder.getVideoFrame();//處理解碼之後的視頻資料} elseif (signal == 1) {decodedAudio = ffdecoder.getAudioFrame();//處理解碼之後的音頻資料} else if (signal == -1) {break;}}

完成編碼後還需要調用FFmpegDecoder對象的close方法,關閉codec和輸入檔案並釋放資源:

testDecoder.close();

注意

  • FFmpegWrapper暫時沒有完整的轉碼功能,如有需要請使用FFmpeg提供的格式轉換工具ffmpeg.exe。
  • 上面的介紹只涉及到一部分FFmpegWrapper的公用API,詳細的API介紹和其他細節見FFmpegWrapper API參考(upcoming)。
  • farthinker只是一個web開發人員,對音視頻的瞭解實在有限,所以FFmpegWrapper肯定存在一些潛在的問題,歡迎大家積極批評指正。
下載FFmpegWrapper
  • 動態庫檔案(2008/8/5):FFmpegWrapper (320)
  • 原始碼(2008/8/5):FFmpegWrapper原始碼 (426)
FFmpegWrapper的未來

就像上面提到的那樣,我只是一個web開發人員,不是音視頻方面的專業人員。因為項目中有一些簡單的編碼需求,我才編寫了FFmpegWrapper。我希望FFmpegWrapper能協助像我這樣的音視頻的菜鳥,能讓剛接觸FFmpeg的朋友少走彎路。當然,我的能力和精力實在有限,今後如果沒有更多的編解碼需求,我可能很難抽出大把時間繼續完善FFmepgWrapper。但我真心希望FFmpegWrapper能繼續走下去,所以有心和我一起繼續編寫FFmpegWrapper朋友請和我聯絡。


下面介紹的API已淘汰,請下載最新版本的原始碼,並參考其注釋。新版本主要由John編寫,在舊版本的基礎上做了很多改進。



轉帖:http://weiyinchao88.iteye.com/blog/1414109

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.