日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

FFmpeg的C++封装:FFmpegWrapper

發布時間:2023/12/18 c/c++ 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FFmpeg的C++封装:FFmpegWrapper 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

下面介紹的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視頻的參數:

view plaincopy to clipboardprint?
  • //指定視頻參數,從左到右分別是:寬、高、像素格式、比特率、幀率
  • FFmpegVideoParam videoParam(352, 288, PIX_FMT_YUV420P, 400000, 25);
  • //指定視頻參數,從左到右分別是:比特率、采樣率、聲道數
  • FFmpegAudioParam audioParam(64000, 44100, 2);
  • 若視頻中沒有視頻流(音頻流),則可以初始化一個空的FFmpegVideoParam(FFmpegAudioParam):

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

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

    view plaincopy to clipboardprint?
  • 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:

    view plaincopy to clipboardprint?
  • 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和輸出文件:

    view plaincopy to clipboardprint?
  • 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)方法來逐幀的編碼并輸出視(音)頻了:

    view plaincopy to clipboardprint?
  • //其中videoFrameData是uint8_t *(unsigned char *)類型的參數
  • testEncoder.writeVideoFrame(videoFrameData);

  • //其中audioFrameData是short *類型的參數
  • testEncoder.writeAudioFrame(audioFrameData);
  • 如果編碼之后不需要輸出,即沒有輸出文件,則使用encodeVideoFrame和getVideoBuffer(encodeAudioFrame和getAudioBuffer)方法來編碼和獲得編碼后的數據:

    view plaincopy to clipboardprint?
  • //其中videoFrameData是uint8_t *(unsigned char *)類型的參數
  • testEncoder.encodeVideoFrame(videoFrameData);
  • uint8_t *encodedVideo = testEncoder.getVideoBuffer();

  • //其中audioFrameData是short *類型的參數
  • testEncoder.encodeAudioFrame(audioFrameData);
  • uint8_t *encodedAudio = testEncoder.getAudioBuffer();
  • 編碼的過程中,還可以獲得音視頻的時間戳(pts)來處理音視頻同步(暫不適用于沒有輸出文件的情況),下面是一個例子:

    view plaincopy to clipboardprint?
  • short*audioData;
  • uint8_t *videoData;
  • doublevideoPts, 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和輸出文件并釋放資源:

    view plaincopy to clipboardprint?
  • testEncoder.close();
  • 使用FFmpegWrapper解碼音視頻

    初始化FFmpegDecoder對象

    首先初始化一個FFmpegDecoder對象,并傳入輸入文件的名稱(包括路徑、名字和后綴):

    view plaincopy to clipboardprint?
  • FFmpegDecoder testDecoder("test.flv");
  • 逐幀解碼音視頻

    開始解碼之前還需要先調用FFmpegDecoder對象的open方法,打開相應的codec和輸入文件:

    view plaincopy to clipboardprint?
  • FFmpegDecoder testDecoder("test.flv");

  • testDecoder.open();
  • 然后就可以調用FFmpegDecoder對象的decodeFrame方法來逐幀的解碼音視頻文件了:

    view plaincopy to clipboardprint?
  • //decodeFrame的返回值表示當前解碼的幀的狀態:
  • //?? 0 - 視頻幀
  • //?? 1 - 音頻幀
  • // -1 - 文件末尾或解碼出錯
  • intsignal = testDecoder.decodeFrame()
  • 解碼之后可以通過FFmpegDecoder對象的getVideoFrame(getAudioFrame)方法來獲得解碼后的視(音)頻數據,下面是一個完整的例子:

    view plaincopy to clipboardprint?
  • intsignal;
  • 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();
  • //處理解碼之后的音頻數據
  • } elseif(signal == -1) {
  • break;
  • }
  • }
  • 完成編碼后還需要調用FFmpegDecoder對象的close方法,關閉codec和輸入文件并釋放資源:

    view plaincopy to clipboardprint?
  • 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朋友請和我聯系。


    總結

    以上是生活随笔為你收集整理的FFmpeg的C++封装:FFmpegWrapper的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。