FFMPEG學(xué)習(xí)第三篇--編譯x264并使用x264壓縮視頻

一:編碼介紹

軟編碼:使用cpu進(jìn)行編碼。
硬編碼:使用顯卡GPU專用的DSP\FPGA\ASIC芯片等硬件進(jìn)行編碼。
軟編碼的特點(diǎn)是升級(jí)方便,實(shí)現(xiàn)簡單,但是cpu負(fù)載中,性能低。硬編碼性能高。

在H.265之前,H.264一直是新一代的編碼標(biāo)準(zhǔn)。H265主要是用來滿足4
k,8k視頻的需求,H.264以高壓縮高質(zhì)量和支持多種網(wǎng)絡(luò)流媒體傳輸而聞名。經(jīng)過h264標(biāo)準(zhǔn)對視頻進(jìn)行壓縮編碼,能夠有效減小視頻的文件大小,這主要是受益于他的低碼率。與MPEG-2和MPEG-4 ASP等壓縮技術(shù)相比,H.264壓縮技術(shù)節(jié)省來用戶的下載時(shí)間和流量。

H.264只是一個(gè)標(biāo)準(zhǔn),具體實(shí)現(xiàn)包括JM,T264,x264。而由于種種原因,JM,T264等實(shí)現(xiàn)工具,并不能很好地繼續(xù)完成我們的需求,因此x264便成了互聯(lián)網(wǎng)世界中主流的實(shí)現(xiàn)H.264標(biāo)準(zhǔn)的編碼工具。

FFMPEG默認(rèn)只支持對H.264的解碼,并不支持對H.264的編碼,因此就需要我們手動(dòng)配置FFMPEG來實(shí)現(xiàn)對H.264的編碼。首先我們需要下載x264

二:編譯x264

下載完成之后,我們需要首先編譯x264為靜態(tài)庫,這是因?yàn)镕FMPEG默認(rèn)是通過靜態(tài)鏈接方式來鏈接其他功能庫。我們在編譯ffmpeg時(shí),修改了configure文件,這樣方便生成可以讓android識(shí)別的*.so文件,但是我們編譯x264是生成的靜態(tài)庫,因此不需要修改x264的configure文件。下面我們直接放一個(gè)網(wǎng)上的編譯腳本,build_x264_arm.sh:

#!/bin/bash

NDK=/Users/xiaguangcheng/android/android-sdk-macosx/ndk-bundle
SYSROOT=$NDK/platforms/android-18/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64

CPU=arm
PREFIX=/Users/xiaguangcheng/x264/arm
ADDI_CFLAGS=""
ADDI_LDFLAGS=""

function build_x264
{
./configure \
    --prefix=$PREFIX \
    --disable-shared \
    --disable-asm \
    --enable-static \
    --enable-pic \
    --enable-strip \
    --host=arm-linux-androideabi \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --sysroot=$SYSROOT
    --extra-cflags="-Os -fpic $ADDI_CFLAGS $OPTIMIZE_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS" \
    $ADDITIONAL_CONFIGURE_FLAG
make clean
make -j4
make install
}


build_x264

下面的幾行需要根據(jù)你的電腦來完成配置。同時(shí)在x264文件夾下新建一個(gè)arm的文件夾用來存放編譯之后的文件。

NDK=/Users/xiaguangcheng/android/android-sdk-macosx/ndk-bundle
SYSROOT=$NDK/platforms/android-18/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
CPU=arm
PREFIX=/Users/xiaguangcheng/x264/arm

接著我們通過命令cd x264進(jìn)入到x264文件夾內(nèi),查看新建的build_x264_arm.sh文件的權(quán)限

ls -l build_x264_arm.sh
-rwxrwxrwx  1 xiaguangcheng  staff  733  6 26 20:46 build_x264_arm.sh

如果你的該文件不具備可執(zhí)行權(quán)限,那么就需要手動(dòng)添加可執(zhí)行權(quán)限,添加完權(quán)限之后,記得再查看一下是否成功。

chmod 777 build_x264_arm.sh
ls -l build_x264_arm.sh

如果還沒有安裝yasm那么可以通過homebrew安裝

brew install yasm

否則可能會(huì)報(bào)一個(gè)錯(cuò)誤

if you really want to compile without asm, configure with --disable-asm. make: *** [config.mak] Error 1 Makefile:3: config.mak: No such file or directory

接下來我們在命令行中就可以運(yùn)行該文件進(jìn)行編譯

./build_x264_arm.sh

待編譯結(jié)束后,我們在剛剛創(chuàng)建的arm文件夾中的就可以找到一個(gè).a靜態(tài)庫。


image.png

三:編譯含有x264靜態(tài)庫的ffmpeg動(dòng)態(tài)庫

第一篇中我們講解來如何編譯一個(gè)ffmpeg動(dòng)態(tài)庫,但是那個(gè)動(dòng)態(tài)庫并沒有包含x264,這里我們將x264包含進(jìn)來。因此在編譯ffmpeg動(dòng)態(tài)庫的編譯文件基礎(chǔ)之上進(jìn)行略微的修改即可,buildffmpeg.sh文件內(nèi)容更新如下:

#!/bin/bash
export TMPDIR=/Users/xiaguangcheng/ffmpeg/ffmpeg/ffmpegtemp
NDK=/Users/xiaguangcheng/android/android-sdk-macosx/ndk-bundle
SYSROOT=$NDK/platforms/android-18/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
CPU=arm
PREFIX=/Users/xiaguangcheng/ffmpeg/ffmpeg/android
ADDI_CFLAGS="-marm"

function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--enable-gpl \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-small \
--enable-gpl \
--enable-libx264 \
--enable-yasm \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-I/Users/xiaguangcheng/x264/arm/include" \
--extra-ldflags="-L/Users/xiaguangcheng/x264/arm/lib" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
build_one

主要修改包括以下幾點(diǎn)

--enable-gpl \
--enable-libx264 \
--enable-yasm \
--extra-cflags="-I/Users/xiaguangcheng/x264/arm/include" \
--extra-ldflags="-L/Users/xiaguangcheng/x264/arm/lib" \
  • -I:編譯階段生效的參數(shù),用于指定頭文件的搜索路徑。
  • -L:鏈接階段生效的參數(shù),用于指定鏈接庫的搜索路徑,-l用于指定鏈接庫的名稱,一般兩者一起使用的話,就可以指定動(dòng)態(tài)鏈接庫。

查看該文件是否有執(zhí)行權(quán)限,如果有執(zhí)行權(quán)限

./buildffmpeg.sh

運(yùn)行該命令后即可得到最終的包含x264的ffmpeg的so動(dòng)態(tài)庫。我們也可以通過在編譯過程中打印的日志來查看

image.png

四:使用包含x264的ffmpeg動(dòng)態(tài)庫在android中壓縮視頻

在android中使用ffmpeg執(zhí)行命令,并通過命令來編碼壓縮視頻,利用FFmpeg玩轉(zhuǎn)Android視頻錄制與壓縮(一),這篇博客已經(jīng)說的差不多了,但是根據(jù)我們項(xiàng)目中上傳視頻的需求,我們還需要獲取在編碼壓縮過程中的進(jìn)度,具體思路是通過process來執(zhí)行命令,而不是通過jni調(diào)用ffmpeg來執(zhí)行命令。而上面提到的這篇博客就是通過jni調(diào)用ffmpeg來執(zhí)行命令的。通過android.jar中的Process來執(zhí)行命令,可以獲取到執(zhí)行命令的結(jié)果,由于在執(zhí)行ffmpeg的過程中,會(huì)出現(xiàn)諸如下面這樣的結(jié)果輸出

frame=  125 fps=0.0 q=38.0 size=     176kB time=00:00:08.54 bitrate= 168.7kbits/frame=  298 fps=297 q=35.0 size=     471kB time=00:00:20.03 bitrate= 192.6kbits/frame=  454 fps=302 q=35.0 size=     727kB time=00:00:30.46 bitrate= 195.4kbits/frame=  662 fps=331 q=33.0 size=    1067kB time=00:00:44.37 bitrate= 197.0kbits/frame=  853 fps=341 q=36.0 size=    1386kB time=00:00:57.05 bitrate= 199.0kbits/frame= 1041 fps=347 q=37.0 size=    1719kB time=00:01:09.56 bitrate= 202.4kbits/frame= 1241 fps=354 q=37.0 size=    2063kB time=00:01:22.91 bitrate= 203.8kbits/frame= 1478 fps=369 q=37.0 size=    2475kB time=00:01:38.73 bitrate= 205.3kbits/frame= 1677 fps=372 q=38.0 size=    2815kB time=00:01:51.96 bitrate= 206.0kbits/frame= 1889 fps=378 q=38.0 size=    3181kB time=00:02:06.13 bitrate= 206.6kbits/frame= 2101 fps=382 q=36.0 size=    3535kB time=00:02:20.29 bitrate= 206.4kbits/frame= 2341 fps=390 q=32.0 size=    3931kB time=00:02:36.22 bitrate= 206.1kbits/frame= 2602 fps=400 q=36.0 size=    4393kB time=00:02:53.63 bitrate= 207.3kbits/frame= 2809 fps=401 q=27.0 size=    4728kB time=00:03:07.47 bitrate= 206.6kbits/frame= 3016 fps=406 q=-1.0 Lsize=    5098kB time=00:03:21.01 bitrate= 207.7kbits/s speed=  27x    

那么我們就可以通過先獲取本地視頻的時(shí)長,然后再拿到輸出結(jié)果中的轉(zhuǎn)換時(shí)長來查看編碼進(jìn)度。上面輸出中的size并不是原視頻的size,而是編碼之后的新視頻已經(jīng)生成的size,因此不可以參考。但是我們編碼只是壓縮了大小,并沒有改變時(shí)長,因此時(shí)間可以用來參考
1:獲取本地視頻時(shí)長

Cursor mCursor = mContentResolver.query(
                MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                null, null, null,
                MediaStore.MediaColumns.DATE_ADDED + " DESC");
            int columnIndex1 = mCursor.getColumnIndex(MediaStore.Video.Media.DURATION);
long millSeconds = mCursor.getLong(columnIndex1);

2:獲取ffmpeg命令輸出結(jié)果

String [] cmd =new String []{"ffmpeg","-i","xiaugangcheng.mp4","xia.mp4"};
Process process = new ProcessBuilder()
       .command(cmd)
       .redirectErrorStream(true)
       .start();
   try {
     InputStream in = process.getInputStream();
     OutputStream out = process.getOutputStream();
     readStream(in);

    } finally {
     process.destroy();
   }

3:根據(jù)輸出結(jié)果獲取已轉(zhuǎn)換的視頻時(shí)長

                    String s=""frame=125 fps=0.0 q=38.0 size=176kB time=01:11:08.54 bitrate= 168.7kbits"";
                    int index = s.indexOf("time=");
                    if(index==-1){
                        return;
                    }
                    if(index+5>s.length()||index+13>s.length()){
                        return;
                    }
                    String cmd = s.substring(index+5, index+13);
                    System.out.println(cmd);

                    String[] my =cmd.split(":");
                    int hour =Integer.parseInt(my[0]);
                    int min =Integer.parseInt(my[1]);
                    int sec =Integer.parseInt(my[2]);

                    int totalSec =hour*3600+min*60+sec;
                    int percent =String totalSec *100/ 202;
                    progressDialog.setMessage("Processing\n"+percent+"%");

拿到輸入輸出流,就可以轉(zhuǎn)化為string來提取時(shí)間了

文章參考
初識(shí)FFmpeg編譯那些事
Mac下為Android編譯FFMPEG和x264
在Android上使用FFmpeg壓縮視頻
編譯Android下可執(zhí)行命令的FFmpeg

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 前幾天項(xiàng)目需要壓縮視頻,Github上找了許多庫,要么就是太大,要么就是質(zhì)量不高,其實(shí)我只需要壓縮視頻,最好的方案...
    voiddog閱讀 26,471評論 59 82
  • 原文地址:http://blog.csdn.net/yipie/article/details/7912291 摘...
    冬的天閱讀 7,215評論 1 6
  • FFmpeg X264編碼參數(shù) 目錄 碼率控制 1 X264的preset和tune 2 編碼延時(shí)建議...
    古則閱讀 30,417評論 1 15
  • 0 概述 FFmpeg是一套領(lǐng)先的音視頻多媒體處理開源框架,采用LGPL或GPL許可證。它提供了對音視頻的采集、編...
    但行耕者閱讀 6,936評論 0 19
  • 文/十月云 樓下賣豆?jié){的小伙子 一個(gè)人 一張課桌 一個(gè)保溫箱 矮個(gè)子 暗綠色棉衣 說話謙卑 沒有自信 豆?jié){兩元 手...
    十月云閱讀 626評論 12 49