国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建

這篇具有很好參考價(jià)值的文章主要介紹了Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一,FFmpeg介紹

FFmpeg 是一款流行的開源多媒體處理工具,它可以用于轉(zhuǎn)換、編輯、錄制和流式傳輸音視頻文件。FFmpeg 具有廣泛的應(yīng)用場(chǎng)景,包括視頻編解碼、格式轉(zhuǎn)換、裁剪、合并、濾鏡等等。官網(wǎng):https://ffmpeg.org/

FFmpeg 支持各種常見的音視頻格式,例如 MP4、AVI、FLV、MOV、AAC、MP3、M4A 等等,并且可以通過添加插件支持更多的格式。與其他視頻處理軟件相比,F(xiàn)Fmpeg 優(yōu)勢(shì)在于它的跨平臺(tái)性能好,可以在 Windows、macOS 和 Linux IOS Android等平臺(tái)上運(yùn)行。

FFmpeg 提供了一個(gè)命令行界面(CLI),可以使用它來執(zhí)行各種操作。以下是一些常用的 FFmpeg 命令:

  • 裁剪:從視頻中截取指定時(shí)間段的視頻片段。

    ffmpeg -i input.mp4 -ss 00:01:00 -t 00:00:30 -c copy output.mp4
    
  • 視頻旋轉(zhuǎn):將視頻順時(shí)針或逆時(shí)針旋轉(zhuǎn)指定角度。

    ffmpeg -i input.mp4 -vf "rotate=PI/2" output.mp4
    
  • 視頻拼接:將多個(gè)視頻文件拼接成一個(gè)文件。

    ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4
    
  • 視頻縮放:按比例縮小或放大視頻尺寸。

    ffmpeg -i input.mp4 -vf scale=640:-1 output.mp4
    
  • 音頻提?。簩⒁曨l文件中的音頻提取出來。

    ffmpeg -i input.mp4 -vn -acodec copy output.aac
    
  • 音頻合并:將多個(gè)音頻文件合并為一個(gè)文件。

    ffmpeg -i "concat:input1.mp3|input2.mp3" -acodec copy output.mp3
    
  • 視頻轉(zhuǎn)碼:將一個(gè)視頻文件轉(zhuǎn)換為另一種格式。

    ffmpeg -i input.avi -c:v libx264 -preset slow -crf 22 -c:a libmp3lame -b:a 192k output.mp4
    
  • 視頻加減速:將視頻的播放速度加快或減慢。

    ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" output.mp4
    
  • 音頻加減速:將視頻中的音頻的播放速度加快或減慢。

    ffmpeg -i input.mp4 -vn -af atempo=%.3f output.mp4
    
  • 音頻重采樣

    ffmpeg -y -i input.mp4 -vn -ar 44100 -ac 2  output.mp4
    
  • 視頻轉(zhuǎn)Gif并等比例縮放

    ffmpeg -y -i input.mp4 -vf scale=320:-2 -r 5 output.gif
    
  • 統(tǒng)計(jì)I幀數(shù)量

    ffprobe -show_frames input.mp4 > frames.txt
    cat frames.txt | grep "pict_type=I" |wc -l
    
  • 視頻信息查看 開發(fā)過程中最常用的命令,沒有之一

    ffprobe -v error -show_format -show_streams input.mp4
    

結(jié)果如下:

    [STREAM]
	index=0
	codec_name=h264
	codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
	profile=Baseline
	codec_type=video
	codec_tag_string=avc1
	codec_tag=0x31637661
	width=1920
	height=1080
	coded_width=1920
	coded_height=1080
	closed_captions=0
	film_grain=0
	has_b_frames=0
	sample_aspect_ratio=1:1
	display_aspect_ratio=16:9
	pix_fmt=yuvj420p
	level=40
	color_range=pc
	color_space=smpte170m
	color_transfer=smpte170m
	color_primaries=smpte170m
	chroma_location=left
	field_order=progressive
	refs=1
	is_avc=true
	nal_length_size=4
	id=0x1
	r_frame_rate=30/1
	avg_frame_rate=40230000/1339297
	time_base=1/90000
	start_pts=0
	start_time=0.000000
	duration_ts=1339297
	duration=14.881078
	bit_rate=20028287
	max_bit_rate=N/A
	bits_per_raw_sample=8
	nb_frames=447
	nb_read_frames=N/A
	nb_read_packets=N/A
	extradata_size=33
	DISPOSITION:default=1
	DISPOSITION:dub=0
	DISPOSITION:original=0
	DISPOSITION:comment=0
	DISPOSITION:lyrics=0
	DISPOSITION:karaoke=0
	DISPOSITION:forced=0
	DISPOSITION:hearing_impaired=0
	DISPOSITION:visual_impaired=0
	DISPOSITION:clean_effects=0
	DISPOSITION:attached_pic=0
	DISPOSITION:timed_thumbnails=0
	DISPOSITION:captions=0
	DISPOSITION:descriptions=0
	DISPOSITION:metadata=0
	DISPOSITION:dependent=0
	DISPOSITION:still_image=0
	TAG:creation_time=2021-02-27T07:35:19.000000Z
	TAG:language=eng
	TAG:handler_name=VideoHandle
	TAG:vendor_id=[0][0][0][0]
	[SIDE_DATA]
	side_data_type=Display Matrix
	displaymatrix=
	00000000:            0       65536           0
	00000001:       -65536           0           0
	00000002:            0           0  1073741824
	rotation=-90
	[/SIDE_DATA]
	[/STREAM]
	[STREAM]
	index=1
	codec_name=aac
	codec_long_name=AAC (Advanced Audio Coding)
	profile=LC
	codec_type=audio
	codec_tag_string=mp4a
	codec_tag=0x6134706d
	sample_fmt=fltp
	sample_rate=48000
	channels=2
	channel_layout=stereo
	bits_per_sample=0
	initial_padding=0
	id=0x2
	r_frame_rate=0/0
	avg_frame_rate=0/0
	time_base=1/48000
	start_pts=0
	start_time=0.000000
	duration_ts=715765
	duration=14.911771
	bit_rate=96041
	max_bit_rate=N/A
	bits_per_raw_sample=N/A
	nb_frames=699
	nb_read_frames=N/A
	nb_read_packets=N/A
	extradata_size=2
	DISPOSITION:default=1
	DISPOSITION:dub=0
	DISPOSITION:original=0
	DISPOSITION:comment=0
	DISPOSITION:lyrics=0
	DISPOSITION:karaoke=0
	DISPOSITION:forced=0
	DISPOSITION:hearing_impaired=0
	DISPOSITION:visual_impaired=0
	DISPOSITION:clean_effects=0
	DISPOSITION:attached_pic=0
	DISPOSITION:timed_thumbnails=0
	DISPOSITION:captions=0
	DISPOSITION:descriptions=0
	DISPOSITION:metadata=0
	DISPOSITION:dependent=0
	DISPOSITION:still_image=0
	TAG:creation_time=2021-02-27T07:35:19.000000Z
	TAG:language=eng
	TAG:handler_name=SoundHandle
	TAG:vendor_id=[0][0][0][0]
	[/STREAM]
	[FORMAT]
	filename=input.mp4
	nb_streams=2
	nb_programs=0
	format_name=mov,mp4,m4a,3gp,3g2,mj2
	format_long_name=QuickTime / MOV
	start_time=0.000000
	duration=14.911771
	size=37839486
	bit_rate=20300465
	probe_score=100
	TAG:major_brand=mp42
	TAG:minor_version=0
	TAG:compatible_brands=isommp42
	TAG:creation_time=2021-02-27T07:35:19.000000Z
	TAG:com.android.version=8.1.0
	[/FORMAT]

在FFmpeg工具中,ffprobe是一種用于分析媒體文件的命令行工具,參數(shù)解釋如下:

profile
在H.264/AVC (Advanced Video Coding)視頻編碼標(biāo)準(zhǔn)中,有以下四種預(yù)定義的profile:

  1. Baseline Profile:這是最基本的profile,它定義了一組基本功能,包括單個(gè)參考幀、CAVLC (Context-adaptive Variable Length Coding)、8x8變換等。Baseline Profile可用于低比特率、低延遲和低復(fù)雜度的應(yīng)用。

  2. Main Profile:Main Profile擴(kuò)展了Baseline Profile并增加了一些高級(jí)功能,例如B幀、8x8和4x4變換以及熵編碼模式自適應(yīng)技術(shù)。Main Profile可以提供更好的視頻質(zhì)量和壓縮率,適合于中等比特率的應(yīng)用。

  3. Extended Profile:Extended Profile擴(kuò)展了Main Profile,并添加了更多的高級(jí)功能,例如8x8和4x4變換、支持更高分辨率、更高的比特率和更豐富的顏色空間。Extended Profile適用于高清視頻和廣電級(jí)別的視頻應(yīng)用。

  4. High Profile:High Profile包含所有的H.264/AVC高級(jí)功能,例如無損編碼、多層編碼、亮度調(diào)整等。High Profile通常用于專業(yè)級(jí)別的視頻應(yīng)用,例如數(shù)字電視廣播、藍(lán)光光盤和高清視頻流媒體服務(wù)。
    除了上述四個(gè)預(yù)定義的profile之外,H.264/AVC還支持用戶定義的profile,以根據(jù)具體應(yīng)用需求自定義編解碼器的參數(shù)設(shè)置。

編碼level
在H.264/AVC視頻編碼標(biāo)準(zhǔn)中,Level指的是視頻編碼器的限制條件,例如最大分辨率、最高比特率以及其他一些技術(shù)參數(shù)。這些限制條件與profile不同,因?yàn)樗鼈兺ǔJ艿綄?shí)時(shí)處理硬件設(shè)備的限制。以下是H.264/AVC定義的level:

  1. Level 1:支持最大352x288像素分辨率和1.5 Mbps的解碼速度。

  2. Level 1b:類似于Level 1,但要求使用Baseline Profile。

  3. Level 1.1:支持最大352x480像素分辨率和12 Mbps的解碼速度。

  4. Level 1.2:支持最大720x480像素分辨率和30 Mbps的解碼速度。

  5. Level 1.3:支持最大1280x720像素分辨率和60 Mbps的解碼速度。

  6. Level 2:支持最大1920x1080像素分辨率和60 Mbps的解碼速度。

  7. Level 2.1:支持最大1920x1080像素分辨率和120 Mbps的解碼速度。

  8. Level 2.2:支持最大1920x1080像素分辨率和120 Mbps的解碼速度,并要求使用High Profile。

  9. Level 3:支持最大1920x1080像素分辨率和240 Mbps的解碼速度。

  10. Level 3.1:支持最大1920x1080像素分辨率和240 Mbps的解碼速度,并要求使用High Profile。

  11. Level 3.2:支持最大1920x1080像素分辨率和240 Mbps的解碼速度,并要求使用High Profile和4:2:2色度采樣。

  12. Level 4:支持最大2048x2048像素分辨率和480 Mbps的解碼速度。

  13. Level 4.1:支持最大2048x2048像素分辨率和1 Gbps的解碼速度。

  14. Level 4.2:支持最大2048x2048像素分辨率和1 Gbps的解碼速度,并要求使用High Profile和10位色深。

  15. Level 5:支持最大4096x2304像素分辨率和1 Gbps的解碼速度。

  16. Level 5.1:支持最大4096x2304像素分辨率和2 Gbps的解碼速度。

  17. Level 5.2:支持最大4096x2304像素分辨率和4 Gbps的解碼速度。

需要注意的是,level越高,支持的分辨率和比特率就越高,因此所需的處理能力和存儲(chǔ)空間也越大。同時(shí),實(shí)際可用的level還受到編碼器和解碼器的硬件限制。

DISPOSITION
DISPOSITION是指多媒體文件流(例如音頻、視頻)在其容器中的位置以及是否被默認(rèn)啟用的標(biāo)志。它告訴我們這個(gè)特定的流的角色是什么,并且是否應(yīng)該被自動(dòng)啟用。
以下是一些常見的DISPOSITION標(biāo)志:
default:表示該流是默認(rèn)啟用的。
dub:表示這個(gè)流是一個(gè)雙語(yǔ)版本的語(yǔ)言流。
original:表示這個(gè)流是原始的無損版本。
comment:表示這個(gè)流是注釋版本的。
lyrics:表示這個(gè)流包含歌詞信息。
通過查看DISPOSITION標(biāo)志,我們可以確定每個(gè)音頻或視頻流的作用和啟用狀態(tài),這對(duì)于解析和編輯多媒體文件非常有用。

除了命令行界面之外,F(xiàn)Fmpeg 還提供了許多開發(fā)庫(kù),例如 libavcodec 和 libavformat 等,這些庫(kù)可以幫助您將 FFmpeg 集成到自己的應(yīng)用程序中。

總之,F(xiàn)Fmpeg 是一款強(qiáng)大的多媒體處理工具,可以讓您對(duì)音視頻文件進(jìn)行各種操作。如果您需要在自己的應(yīng)用程序中使用 FFmpeg,可以使用其提供的開發(fā)庫(kù)

二,F(xiàn)Fmpeg編譯

要想把FFmpeg運(yùn)行在移動(dòng)設(shè)備上,就需要使用到交叉編譯,交叉編譯是指在一臺(tái)計(jì)算機(jī)上,使用一個(gè)編譯器將程序或庫(kù)編譯成可以在不同架構(gòu)的計(jì)算機(jī)上運(yùn)行的二進(jìn)制文件。通常情況下,交叉編譯是在開發(fā)人員的計(jì)算機(jī)上完成的,然后將生成的可執(zhí)行文件或庫(kù)文件拷貝到目標(biāo)設(shè)備上運(yùn)行。

2.1 常見的錯(cuò)誤

FFmpeg 交叉編譯一直依賴都是老大難的問題,新手往往要折騰好幾天才能成功編譯
為 Android 編譯 FFmpeg 時(shí),常見的錯(cuò)誤如下:

C compiler test failed.

出現(xiàn)這個(gè)問題一般有兩種情況

  • NDK版本不對(duì),NDK 的版本非常重要,因?yàn)椴煌姹镜?NDK 可能與不同版本的 FFmpeg 不兼容。在下載 NDK 時(shí),請(qǐng)確保使用與您要構(gòu)建的 FFmpeg 版本相匹配的 NDK 版本。
    -NDK路徑寫錯(cuò)了
ld: error: relocation R_AARCH64_ADD_ABS_LO12_NC cannot be used against symbol
  1. 在–extra-ldflags 加入-fPIC
  2. 在鏈接的時(shí)候加入-Bsymbolic,慎重使用
  3. 注意鏈接的時(shí)候的順序 比如libavutil是每個(gè)庫(kù)都需要的,那么就要放在第一個(gè)鏈接
duplicate symbol

–enable-shared --enable-static 同時(shí)打開,在合并so的時(shí)候會(huì)出現(xiàn)重復(fù)的方法

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol “cos”

在編譯以及在把.a文件鏈接到SO的時(shí)候沒有把m,z,android庫(kù)鏈接上

2.2 編譯步驟

2.2.1 下載Android SDK

我們一般通過Android Studio下載SDK,官網(wǎng)地址:https://developer.android.com/?hl=zh-cn
運(yùn)行之后打開設(shè)置,找到Android SDK
SDK Platforms我們一般下最新正式版本就好了,這里最新正式版本為33(Android 13),如圖所示:
Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建

SDK Tools一般都需要選擇上,如圖所示:
Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建

2.2.2下載Android NDK

NDK 我們一般去官網(wǎng)下載對(duì)應(yīng)的版本,地址如下:https://developer.android.com/ndk/downloads?hl=zh-cn
這個(gè)地方我們使用r25c就好了

2.2.3 安裝必備的軟件

MAC需要安裝Xcode Command Line Tools 地址:https://developer.apple.com/download/all/?q=xcode
Linux需要安裝curl git yasm

2.2.4 Start build

A 基礎(chǔ)build

需要下載一個(gè)成品腳本,地址:https://github.com/Javernaut/ffmpeg-android-maker 這個(gè)腳本我親測(cè)在Mac Linux都可以成功Build但是在實(shí)際開發(fā)中還需要做修改(修改完的build腳本工程詳見這里:https://github.com/bookzhan/ffmpeg-android-build)
cd 到腳本目錄,指定SDK目錄,如下:

export ANDROID_SDK_HOME='/Users/guaishou/Library/Android/sdk'
export ANDROID_NDK_HOME='/Users/guaishou/Library/Android/sdk/ndk/AndroidNDK9519653.app/Contents/NDK'

執(zhí)行腳本:
./ffmpeg-android-maker.sh
腳本的執(zhí)行時(shí)間比較長(zhǎng),安靜的等待腳本執(zhí)行完成,腳本執(zhí)行完成之后,生成的SO在output目錄下,如圖所示:
Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建
Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建

可以看到,這個(gè)腳本構(gòu)建是不能直接用于開發(fā),主要有以下問題:

  1. 可以看到這個(gè)腳本構(gòu)建的結(jié)構(gòu)有多個(gè)SO,這在開發(fā)中顯得不是很優(yōu)雅,我們需要做的是把這些SO合并成一個(gè)SO
  2. 構(gòu)建出來的SO很大,包大小遭不住
  3. 在構(gòu)建的時(shí)候我們常用的庫(kù)libmp3lame,libx264(libx264是GPL協(xié)議的,要注意安全合規(guī))沒有編譯進(jìn)去
B 多個(gè)SO合并成一個(gè)SO

要想把多個(gè)SO合并成一個(gè)SO,那么就需要把FFmpeg編譯成靜態(tài)庫(kù),有關(guān)靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)的解釋如下:

靜態(tài)庫(kù)是編譯時(shí)鏈接到應(yīng)用程序中的,它將庫(kù)文件的全部?jī)?nèi)容復(fù)制到應(yīng)用程序中。這意味著在運(yùn)行時(shí),所有的庫(kù)函數(shù)都已經(jīng)存在于應(yīng)用程序中,不需要再進(jìn)行加載。由于靜態(tài)庫(kù)已經(jīng)被完全鏈接到應(yīng)用程序中,因此它們的大小通常比動(dòng)態(tài)庫(kù)更大,但執(zhí)行速度更快,因?yàn)闆]有額外的加載和解析操作。同時(shí),使用靜態(tài)庫(kù)可以避免版本沖突和依賴問題,因?yàn)槊總€(gè)應(yīng)用程序都會(huì)使用自己的一份庫(kù)文件副本。

相反,動(dòng)態(tài)庫(kù)是在運(yùn)行時(shí)動(dòng)態(tài)加載的,只有當(dāng)需要使用庫(kù)函數(shù)時(shí)才會(huì)被加載到內(nèi)存中。由于動(dòng)態(tài)庫(kù)僅在需要時(shí)才加載,因此它們的大小通常比靜態(tài)庫(kù)小,但執(zhí)行速度可能稍慢,因?yàn)樾枰M(jìn)行額外的加載和解析操作。另外,由于多個(gè)應(yīng)用程序可以共享相同的庫(kù)文件,因此動(dòng)態(tài)庫(kù)提供了更好的資源利用率。

總之,靜態(tài)庫(kù)是在編譯時(shí)鏈接到應(yīng)用程序中的,而動(dòng)態(tài)庫(kù)是在運(yùn)行時(shí)動(dòng)態(tài)加載的。靜態(tài)庫(kù)的優(yōu)點(diǎn)是執(zhí)行速度更快,依賴和版本控制更容易,而動(dòng)態(tài)庫(kù)的優(yōu)點(diǎn)是更小的庫(kù)文件大小和更好的資源利用率??梢杂梦募缶Y做簡(jiǎn)單的區(qū)分:靜態(tài)庫(kù)文件后綴為.a, 動(dòng)態(tài)庫(kù)文件后綴為.so

步驟如下:

  1. 首選我們需要修改ffmpeg-android-maker-master/scripts/ffmpeg/build.sh 文件把–disable-static 改成–enable-static 再次build 的時(shí)候就可以在ffmpeg-android-maker-master/build目錄下看到.a文件已經(jīng)生成了(在調(diào)試腳本的時(shí)候可以在后面加-abis=arm64-v8a 參數(shù),只是構(gòu)建64位的庫(kù),這個(gè)構(gòu)建時(shí)間就會(huì)短很多)
  2. 合并.a文件
${FAM_CC} -shared -o ${STATIC_LIB_DIR}/${OUTPUT_SO_NAME} 
  -Wl,--whole-archive,-Bsymbolic 
  ${STATIC_LIB_DIR}/libavutil.a 
  ${STATIC_LIB_DIR}/libavcodec.a 
  ${STATIC_LIB_DIR}/libavfilter.a 
  ${STATIC_LIB_DIR}/libswresample.a 
  ${STATIC_LIB_DIR}/libavformat.a 
  ${STATIC_LIB_DIR}/libswscale.a 
  -Wl,--no-whole-archive
${FAM_STRIP} --strip-unneeded ${STATIC_LIB_DIR}/${OUTPUT_SO_NAME}
#FAM_CC STATIC_LIB_DIR FAM_STRIP 都是export-build-variables.sh生成的環(huán)境變量,F(xiàn)AM_CC其實(shí)就是clang(aarch64-linux-android21-clang系列)  --whole-archive指的是把全部代碼都寫入到so中,不管是否使用到了
#FAM_STRIP --strip-unneeded 標(biāo)識(shí)剔除debug信息,減少so大小,其實(shí)Android在打包的時(shí)候會(huì)對(duì)所有so執(zhí)行這個(gè)操作
#-Bsymbolic是解決ld: error: relocation R_AARCH64_ADD_ABS_LO12_NC cannot be used against symbol 'ff_tx_tab_32_float'; recompile with -fPIC錯(cuò)誤的關(guān)鍵,但是不要輕易使用,盡量去解決編譯問題,否則在運(yùn)行的時(shí)候會(huì)出問題
#在后面寫入-Wl,--no-whole-archive是為了解決重復(fù)符號(hào)表的問題,表示只對(duì)接下來的目標(biāo)文件執(zhí)行局部符號(hào)綁定。這樣,就可以將不必要的符號(hào)從最終的符號(hào)表中刪除,減小輸出文件的大小,并避免一些潛在的問題。
#需要主要這個(gè)合并的順序?。?!
C FFmpeg裁剪

so合并的文件的問題解決了,但是合并的so會(huì)顯得很大,這是因?yàn)槟J(rèn)是把FFmpeg的代碼全部編譯了,我們需要做一些裁剪,去掉我們不用的代碼
在不知道有那些配置可以選擇的時(shí)候,可以在FFmpeg源碼下執(zhí)行./configure 這樣默認(rèn)會(huì)把所有支持的配置都列出來,然后依次去掉不必要的配置就好
最終scripts/ffmpeg/build.sh文件的樣式如下:

#!/usr/bin/env bash

case $ANDROID_ABI in
  x86)
    # Disabling assembler optimizations, because they have text relocations
    EXTRA_BUILD_CONFIGURATION_FLAGS="$EXTRA_BUILD_CONFIGURATION_FLAGS --disable-neon --disable-asm"
    ;;
  x86_64)
    EXTRA_BUILD_CONFIGURATION_FLAGS="$EXTRA_BUILD_CONFIGURATION_FLAGS --disable-neon --disable-asm"
    ;;
  armeabi-v7a)
    EXTRA_BUILD_CONFIGURATION_FLAGS="$EXTRA_BUILD_CONFIGURATION_FLAGS --enable-neon --disable-asm --enable-inline-asm"
    ;;
  arm64-v8a)
    EXTRA_BUILD_CONFIGURATION_FLAGS="$EXTRA_BUILD_CONFIGURATION_FLAGS --enable-neon --disable-asm --enable-inline-asm"
    ;;
esac

if [ "$FFMPEG_GPL_ENABLED" = true ] ; then
    EXTRA_BUILD_CONFIGURATION_FLAGS="$EXTRA_BUILD_CONFIGURATION_FLAGS --enable-gpl"
fi

# Preparing flags for enabling requested libraries
ADDITIONAL_COMPONENTS=
for LIBARY_NAME in ${FFMPEG_EXTERNAL_LIBRARIES[@]}
do
  ADDITIONAL_COMPONENTS+=" --enable-$LIBARY_NAME"
  case $LIBARY_NAME in
        libx264)
          ADDITIONAL_COMPONENTS+=" --enable-encoder=libx264"
          ;;
        libmp3lame)
          ADDITIONAL_COMPONENTS+=" --enable-decoder=mp3"
          ;;
        *)
          echo "Unknown ADDITIONAL_COMPONENTS LIBARY_NAME: $LIBARY_NAME"
          ;;
  esac
done

echo ADDITIONAL_COMPONENTS=${ADDITIONAL_COMPONENTS}

# Referencing dependencies without pkgconfig
DEP_CFLAGS="-I${BUILD_DIR_EXTERNAL}/${ANDROID_ABI}/include"
DEP_LD_FLAGS="-L${BUILD_DIR_EXTERNAL}/${ANDROID_ABI}/lib $FFMPEG_EXTRA_LD_FLAGS"

./configure 
  --prefix=${BUILD_DIR_FFMPEG}/${ANDROID_ABI} 
  --enable-cross-compile 
  --enable-small 
  --target-os=android 
  --arch=${TARGET_TRIPLE_MACHINE_ARCH} 
  --sysroot=${SYSROOT_PATH} 
  --cc=${FAM_CC} 
  --cxx=${FAM_CXX} 
  --ld=${FAM_LD} 
  --ar=${FAM_AR} 
  --as=${FAM_CC} 
  --nm=${FAM_NM} 
  --ranlib=${FAM_RANLIB} 
  --strip=${FAM_STRIP} 
  --extra-cflags="-O3 -fPIC -lm -lz -landroid $DEP_CFLAGS" 
  --extra-ldflags="$DEP_LD_FLAGS" 
  --disable-shared 
  --enable-static 
  --disable-vulkan 
  --disable-symver 
  --disable-doc 
  --disable-htmlpages 
  --disable-manpages 
  --disable-podpages 
  --disable-txtpages 
  --disable-ffplay 
  --disable-ffmpeg 
  --disable-ffprobe 
  --disable-avdevice 
  --disable-bsfs 
  --disable-devices 
  --disable-protocols 
  --disable-postproc 
  --enable-protocol=file 
  --enable-protocol=concat 
  --disable-parsers 
  --disable-demuxers 
  --enable-demuxer=mov 
  --enable-demuxer=mp3 
  --enable-demuxer=image2 
  --enable-demuxer=gif 
  --enable-demuxer=wav 
  --enable-demuxer=asf 
  --enable-demuxer=flv 
  --enable-demuxer=avi 
  --enable-demuxer=webm_dash_manifest 
  --enable-demuxer=matroska 
  --enable-demuxer=mpegts 
  --disable-decoders 
  --enable-decoder=aac 
  --enable-decoder=png 
  --enable-decoder=h264 
  --enable-decoder=mp3 
  --enable-decoder=mjpeg 
  --enable-decoder=mpeg4 
  --enable-decoder=gif 
  --enable-decoder=pcm_s16le 
  --enable-decoder=hevc 
  --enable-decoder=msmpeg4v1 
  --enable-decoder=msmpeg4v2 
  --enable-decoder=msmpeg4v3 
  --enable-decoder=wmav1 
  --enable-decoder=wmav2 
  --enable-decoder=flv 
  --enable-decoder=adpcm_swf 
  --enable-decoder=ac3 
  --enable-decoder=vp8 
  --enable-decoder=vorbis 
  --enable-decoder=mpeg2video 
  --enable-decoder=mp2 
  --enable-decoder=indeo4 
  --enable-decoder=amrnb 
  --disable-muxers 
  --enable-muxer=mov 
  --enable-muxer=mp4 
  --enable-muxer=image2 
  --enable-muxer=mp3 
  --enable-muxer=ipod 
  --enable-muxer=gif 
  --disable-encoders 
  --enable-encoder=aac 
  --enable-encoder=png 
  --enable-encoder=mjpeg 
  --enable-encoder=gif 
  --enable-swscale 
  --disable-filters 
  --enable-filter=crop 
  --enable-filter=scale 
  --enable-filter=afade 
  --enable-filter=atempo 
  --enable-filter=copy 
  --enable-filter=aformat 
  --enable-filter=overlay 
  --enable-filter=vflip 
  --enable-filter=hflip 
  --enable-filter=transpose 
  --enable-filter=volume 
  --enable-filter=rotate 
  --enable-filter=apad 
  --enable-filter=amerge 
  --enable-filter=aresample 
  --enable-filter=setpts 
  --enable-filter=fps 
  --enable-filter=palettegen 
  --enable-filter=paletteuse 
  --enable-filter=trim 
  --enable-filter=null 
  --enable-filter=overlay 
  --enable-filter=format 
  --enable-filter=atrim 
  --enable-filter=split 
  --enable-filter=amix 
  --enable-filter=anull 
  --enable-filter=adelay 
  --enable-zlib 
  --enable-jni 
  --enable-nonfree 
  --enable-mediacodec 
  --enable-version3 
  --pkg-config=${PKG_CONFIG_EXECUTABLE} 
  ${EXTRA_BUILD_CONFIGURATION_FLAGS} 
  ${ADDITIONAL_COMPONENTS} || exit 1

${MAKE_EXECUTABLE} clean
${MAKE_EXECUTABLE} -j${HOST_NPROC}
${MAKE_EXECUTABLE} install


export STATIC_LIB_DIR=${BUILD_DIR_FFMPEG}/${ANDROID_ABI}/lib
export EXTERNAL_LIB_DIR=${INSTALL_DIR}/lib
echo STATIC_LIB_DIR=${STATIC_LIB_DIR}
echo EXTERNAL_LIB_DIR=${EXTERNAL_LIB_DIR}
echo FAM_CC=${FAM_CC}

EXTERNAL_STATIC_LIB_PATH=""
for LIBARY_NAME in ${FFMPEG_EXTERNAL_LIBRARIES[@]}
do
  EXTERNAL_STATIC_LIB_PATH+="${EXTERNAL_LIB_DIR}/${LIBARY_NAME}.a "
done
echo EXTERNAL_STATIC_LIB_PATH=${EXTERNAL_STATIC_LIB_PATH}

${FAM_CC} -shared -o ${STATIC_LIB_DIR}/${OUTPUT_SO_NAME} 
  -Wl,--whole-archive 
  ${EXTERNAL_STATIC_LIB_PATH}
  ${STATIC_LIB_DIR}/libavutil.a 
  ${STATIC_LIB_DIR}/libavcodec.a 
  ${STATIC_LIB_DIR}/libavfilter.a 
  ${STATIC_LIB_DIR}/libswresample.a 
  ${STATIC_LIB_DIR}/libavformat.a 
  ${STATIC_LIB_DIR}/libswscale.a 
  -Wl,--no-whole-archive -lm -lz -landroid

OUTPUT_CONFIG_HEADERS_DIR=${OUTPUT_DIR}/include/${ANDROID_ABI}
mkdir -p ${OUTPUT_CONFIG_HEADERS_DIR}
cp config.h ${OUTPUT_CONFIG_HEADERS_DIR}/config.h

${FAM_STRIP} --strip-unneeded ${STATIC_LIB_DIR}/${OUTPUT_SO_NAME}

腳本說明

  1. 從Android 5.0開始,默認(rèn)情況下所有設(shè)備都支持NEON指令集,在編譯的時(shí)候盡量打開NEON,這樣性能會(huì)更好
  2. asm指的是匯編優(yōu)化,這樣代碼執(zhí)行性能會(huì)更好,但是在FFmpeg上編譯一般使用inline-asm(內(nèi)聯(lián)匯編),因?yàn)槎胀▍R編需要單獨(dú)編寫成匯編代碼文件,增加了額外的編譯鏈接過程,很容易鏈接失敗,而且內(nèi)聯(lián)匯編執(zhí)行效率更高
D 添加常用的第三方庫(kù)

在音視頻開發(fā)中,我們一般會(huì)使用一些優(yōu)秀的第三方庫(kù),如對(duì)Mp3支持的庫(kù)libmp3lame,H264軟編庫(kù)libx264(在移動(dòng)端我們一般不使用H265進(jìn)行軟編,主要原因在于H265軟編對(duì)性能消耗要比H264大得多,
在執(zhí)行構(gòu)建命令的時(shí)候啟用./ffmpeg-android-maker.sh --enable-libmp3lame --enable-libx264就好了,最后在鏈接的時(shí)候把對(duì)應(yīng)的.a文件鏈接在一起就好了,如上完整的scripts/ffmpeg/build.sh文件

3.Android 開發(fā)環(huán)境搭建

3.1 新建工程

新建工程,選擇Native c++,然后一直點(diǎn)Next就好了
Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建

Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建

指定ndk版本
ndk版本一般要在各個(gè)開發(fā)者直接統(tǒng)一,寫法為,在build.gradle->android下面寫,如下
ndkVersion ‘25.2.9519653’

3.2 cmake簡(jiǎn)介

其中cpp目錄下的CMakeLists.txt文件是構(gòu)建so的關(guān)鍵文件,俗稱cmake文件,如下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.18.1)

# Declares and names the project.

project("ffmpegtest")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        ffmpegtest

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        common/BZLogUtil.cpp
        native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        ffmpegtest

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

3.2.1 cmake基本語(yǔ)法

cmake的基本語(yǔ)法和C類似,都是通過方法名()的方式來使用的如:

project('ffmpegtest') #指定了工程的名稱,非必選

條件語(yǔ)句

if(condition)
  # do something
elseif(condition2)
  # do something else
else()
  # do another thing
endif()

循環(huán)語(yǔ)句

foreach(loop_var RANGE start end [step])
  # do something
endforeach()

while(condition)
  # do something
endwhile()

函數(shù)

函數(shù)由命令組成,通過 function(func_name [args...]) 定義,可以在任意位置調(diào)用。

function(hello_world)
  message("Hello World!")
endfunction()

hello_world()

3.2.2 cmake變量的使用與定義

變量在 CMake 中以 $ 開頭,有以下幾種類型:

  • 內(nèi)置變量:如 ${CMAKE_CURRENT_LIST_DIR} 表示當(dāng)前 CMake 文件所在的目錄。
  • 環(huán)境變量:如 $ENV{PATH} 表示系統(tǒng)環(huán)境變量 PATH 的值。
  • 用戶定義變量:如 set(VAR_NAME value),通過 ${VAR_NAME} 引用。

3.2.3 常見的用法

其實(shí)上面的很少用,我們來看一個(gè)稍微復(fù)雜一點(diǎn)的,工作中掌握這么多就夠用了,如下:

	# For more information about using CMake with Android Studio, read the
	# documentation: https://d.android.com/studio/projects/add-native-code.html
	
	# Sets the minimum version of CMake required to build the native library.
	
	#這個(gè)是必選的
	cmake_minimum_required(VERSION 3.4.1)
	
	# Creates and names a library, sets it as either STATIC
	# or SHARED, and provides the relative paths to its source code.
	# You can define multiple libraries, and CMake builds them for you.
	# Gradle automatically packages shared libraries with your APK.
	#添加宏
	if (${CMAKE_BUILD_TYPE} STREQUAL Debug)
	    add_definitions(-DDEBUG_TYPE)
	endif()
	
	#添加整個(gè)目錄的源碼作為編譯對(duì)象
	aux_source_directory(./glprogram DIR_GLPROGRAM_SRCS)
	aux_source_directory(./mediaedit DIR_MEDIAEDIT_SRCS)
	aux_source_directory(./player DIR_PLAYER_SRCS)
	aux_source_directory(./soundtouch DIR_SOUNDTOUCH_SRCS)
	
	add_library( # Sets the name of the library.
	        bzmedia
	
	        # Sets the library as a shared library.
	        SHARED
	
	        # Provides a relative path to your source file(s).
	        ./jni/android_bzmedia.cpp
	        ./jni/ffmpeg_base_info.cpp
	        ./jni/OnActionListener.cpp
	        ./jni/ffmpeg_audio_player.cpp
	        ./jni/video_edit_sdk.cpp
	        ./jni/jni_VideoFrameGetter.cpp
	        ./jni/video_recorder_jni.cpp
	        ./jni/android_gl_program.cpp
	        ./jni/jni_BZRenderEngine.cpp;
	        ./jni/video_player_jni.cpp;
	        ./jni/soundtouch_jni.cpp;
	
	
	        ./common/BZLogUtil.cpp
	        ./common/bz_time.cpp
	        ./common/JvmManager.cpp
	        ./common/GLUtil.cpp
	        ./common/PngReader.cpp
	
	        ${DIR_MEDIAEDIT_SRCS}
	
	        ./glutils/FrameBufferUtils.cpp;
	        ./glutils/GLImageTextureUtil.cpp;
	        ./glutils/GLMatrixUtils.cpp;
	        ./glutils/MatrixVaryTools.cpp;
	        ./glutils/CropTextureUtil.cpp;
	        ./glutils/BZRenderEngine.cpp;
	        ./glutils/VideoTextureManger.cpp;
	        ./glutils/EGLContextUtil.cpp;
	        ./glutils/TextureConvertYUVUtil.cpp;
	        ./glutils/TextureUtil.cpp;
	
	        ${DIR_GLPROGRAM_SRCS}
	        ${DIR_PLAYER_SRCS}
	        ${DIR_SOUNDTOUCH_SRCS}
	
	        ./recorder/VideoRecorder.cpp
	
	        ./utils/AdjustConfigUtil.cpp
	        ./utils/PcmDeque.cpp
	
	        ./permission/base64.c
	        ./permission/PermissionUtil.cpp
	        )
	
	# Searches for a specified prebuilt library and stores the path as a
	# variable. Because CMake includes system libraries in the search path by
	# default, you only need to specify the name of the public NDK library
	# you want to add. CMake verifies that the library exists before
	# completing its build.
	configure_file(${Project_SOURCE_DIR}/lib/${ANDROID_ABI}/libbzffmpeg.so ${Project_BINARY_DIR}/libbzffmpeg.so COPYONLY)
	configure_file(${Project_SOURCE_DIR}/lib/${ANDROID_ABI}/libbzffmpegcmd.so ${Project_BINARY_DIR}/libbzffmpegcmd.so COPYONLY)
	
	#ffmpeg
	add_library(bzffmpeg-lib
	        SHARED
	        IMPORTED)
	set_target_properties(bzffmpeg-lib
	        PROPERTIES IMPORTED_LOCATION
	        libbzffmpeg.so)
	#ffmpegcmd
	add_library(bzffmpegcmd-lib
	        SHARED
	        IMPORTED)
	set_target_properties(bzffmpegcmd-lib
	        PROPERTIES IMPORTED_LOCATION
	        libbzffmpegcmd.so)
	add_library(yuv-lib
	        STATIC
	        IMPORTED)
	set_target_properties(yuv-lib
	        PROPERTIES IMPORTED_LOCATION
	        ${Project_SOURCE_DIR}/lib/${ANDROID_ABI}/libyuv_static.a)
	
	#添加系統(tǒng)庫(kù)
	find_library(log-lib log)
	find_library(m-lib m)
	find_library(z-lib z)
	find_library(android-lib android)
	find_library(EGL-lib EGL)
	find_library(jnigraphics-lib jnigraphics)
	find_library(GLES-lib GLESv2)
	find_library(OpenSLES-lib OpenSLES)
	
	
	include_directories(
	        ./
	        ./include/
	        ./common
	        ./bean
	        ./cmdutilt
	        ./include
	        ./utils
	        ./permission
	        ./include/libavcodec
	        ./include/libavdevice
	        ./include/libavfilter
	        ./include/libavformat
	        ./include/libavutil
	        ./include/libpostproc
	        ./include/libswresample
	        ./include/libswscale
	        ./include/libyuv
	        ./include/soundtouch
	)
	# Specifies libraries CMake should link to your target library. You
	# can link multiple libraries, such as libraries you define in this
	# build script, prebuilt third-party libraries, or system libraries.
	
	#把所有庫(kù)連接到最終生成的庫(kù)中
	target_link_libraries( # Specifies the target library.
	        bzmedia
	
	        # Links the target library to the log library
	        # included in the NDK.
	        bzffmpeg-lib bzffmpegcmd-lib yuv-lib ${log-lib} ${m-lib} ${z-lib} ${android-lib} ${EGL-lib} ${GLES-lib} ${jnigraphics-lib} ${OpenSLES-lib})

3.2.4 配置支持的CPU架構(gòu)

默認(rèn)情況下SO會(huì)生成armeabi-v7a,arm64-v8a,x86,x86_64,如果我們只想生成指定的SO,那么在build.gradle文件android->defaultConfig下配置ndk來過濾就好了,如下:

	apply plugin: 'com.android.library'
	apply from: '../config.gradle'
	
	android {
	    compileSdkVersion project.ext.compileSdkVersion
	    defaultConfig {
	        minSdkVersion project.ext.minSdkVersion
	        targetSdkVersion project.ext.targetSdkVersion
	
	        ndk {
	            abiFilters 'armeabi-v7a', 'arm64-v8a'
	        }
	    }
	}

3.3驗(yàn)證FFmpeg編譯是否成功

測(cè)試工程:https://github.com/bookzhan/ffmpegtest
成功標(biāo)準(zhǔn):文章來源地址http://www.zghlxwxcb.cn/news/detail-498827.html

  1. 執(zhí)行System.loadLibrary沒有任何報(bào)錯(cuò)
  2. 能夠成功獲取到編碼器,解碼器,avformat信息,驗(yàn)證代碼如下:
	#include <common/BZLogUtil.h>
	#include <cstring>
	#include "ffmpeg_base_info.h"
	
	
	void printFFmpegBaseInfo() {
	    char buffer[4096];
	    getFFmpegConfigure(buffer);
	    BZLogUtil::logD(buffer);
	
	    memset(buffer, 0, 4096);
	    getFFmpegSupportProtocol(buffer);
	    BZLogUtil::logD(buffer);
	
	    memset(buffer, 0, 4096);
	    getFFmpegSupportAVFormat(buffer);
	    BZLogUtil::logD(buffer);
	
	    memset(buffer, 0, 4096);
	    getFFmpegSupportAVCodec(buffer);
	    BZLogUtil::logD(buffer);
	
	    memset(buffer, 0, 4096);
	    getFFmpegSupportAVFilter(buffer);
	    BZLogUtil::logD(buffer);
	
	    testLib();
	}
	
	int getFFmpegConfigure(char *info) {
	    return sprintf(info, "%sn", avcodec_configuration());;
	}
	
	int getFFmpegSupportProtocol(char *info) {
	    struct URLProtocol *pup = nullptr;
	    int ret = 0;
	    //Input
	    struct URLProtocol **p_temp = &pup;
	    avio_enum_protocols((void **) p_temp, 0);
	    while ((*p_temp) != nullptr) {
	        ret = sprintf(info, "%s[In ][%10s]n", info, avio_enum_protocols((void **) p_temp, 0));
	    }
	    pup = nullptr;
	    //Output
	    avio_enum_protocols((void **) p_temp, 1);
	    while ((*p_temp) != nullptr) {
	        ret = sprintf(info, "%s[Out][%10s]n", info, avio_enum_protocols((void **) p_temp, 1));
	    }
	    return ret;
	}
	
	int getFFmpegSupportAVFormat(char *info) {
	    int ret = 0;
	    void *opaque_in = nullptr;
	    void *opaque_out = nullptr;
	    const AVInputFormat *if_temp = av_demuxer_iterate(&opaque_in);
	    const AVOutputFormat *of_temp = av_muxer_iterate(&opaque_out);
	    //Input
	    while (if_temp != nullptr) {
	        ret = sprintf(info, "%s[In ][%10s]n", info, if_temp->name);
	        if_temp = av_demuxer_iterate(&opaque_in);;
	    }
	    //Output
	    while (of_temp != nullptr) {
	        ret = sprintf(info, "%s[Out][%10s]n", info, of_temp->name);
	        of_temp = av_muxer_iterate(&opaque_out);
	    }
	    return ret;
	}
	
	int getFFmpegSupportAVCodec(char *info) {
	    int ret = 0;
	    void *opaque = nullptr;
	    const AVCodec *c_temp = av_codec_iterate(&opaque);
	
	    while (c_temp != nullptr) {
	        if (av_codec_is_decoder(c_temp) != 0) {
	            ret = sprintf(info, "%s[Dec]", info);
	        } else {
	            ret = sprintf(info, "%s[Enc]", info);
	        }
	        switch (c_temp->type) {
	            case AVMEDIA_TYPE_VIDEO:
	                sprintf(info, "%s[Video]", info);
	                break;
	            case AVMEDIA_TYPE_AUDIO:
	                sprintf(info, "%s[Audio]", info);
	                break;
	            default:
	                sprintf(info, "%s[Other]", info);
	                break;
	        }
	        ret = sprintf(info, "%s[%10s]n", info, c_temp->name);
	        c_temp = av_codec_iterate(&opaque);
	    }
	    return ret;
	}
	
	int getFFmpegSupportAVFilter(char *info) {
	    int ret = 0;
	    void *opaque = nullptr;
	    const AVFilter *f_temp = av_filter_iterate(&opaque);
	    while (nullptr != f_temp) {
	        ret = sprintf(info, "%s[%10s]n", info, f_temp->name);
	        f_temp = av_filter_iterate(&opaque);
	    }
	    return ret;
	}
	
	int testLib() {
	    const AVCodec *avCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
	    if (nullptr == avCodec) {
	        BZLogUtil::logD("avcodec_find_decoder AV_CODEC_ID_H264 未發(fā)現(xiàn)");
	    } else {
	        BZLogUtil::logD("avcodec_find_decoder AV_CODEC_ID_H264 正常");
	    }
	    const AVCodec *avCodecAAC = avcodec_find_decoder(AV_CODEC_ID_AAC);
	    if (nullptr == avCodecAAC) {
	        BZLogUtil::logD("avcodec_find_decoder AV_CODEC_ID_AAC 未發(fā)現(xiàn)");
	    } else {
	        BZLogUtil::logD("avcodec_find_decoder AV_CODEC_ID_AAC 正常");
	    }
	
	
	    const AVCodec *avCodecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
	    if (nullptr == avCodecEncoder) {
	        BZLogUtil::logD("avcodec_find_encoder AV_CODEC_ID_H264 未發(fā)現(xiàn)");
	    } else {
	        BZLogUtil::logD("avcodec_find_encoder AV_CODEC_ID_H264 正常");
	    }
	
	
	    const AVCodec *avCodecDecoderMp3 = avcodec_find_decoder(AV_CODEC_ID_MP3);
	    if (nullptr == avCodecDecoderMp3) {
	        BZLogUtil::logD("avcodec_find_decoder AV_CODEC_ID_MP3 未發(fā)現(xiàn)");
	    } else {
	        BZLogUtil::logD("avcodec_find_decoder AV_CODEC_ID_MP3 正常");
	    }
	
	
	    const AVCodec *avCodecAACEncoder = avcodec_find_encoder(AV_CODEC_ID_AAC);
	    if (nullptr == avCodecAACEncoder) {
	        BZLogUtil::logD("avcodec_find_encoder AV_CODEC_ID_AAC 未發(fā)現(xiàn)");
	    } else {
	        BZLogUtil::logD("avcodec_find_encoder AV_CODEC_ID_AAC 正常");
	    }
	    return 0;
	}

到了這里,關(guān)于Android音視頻開發(fā)實(shí)戰(zhàn)01-環(huán)境搭建的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 音視頻開發(fā):音頻編碼原理+采集+編碼實(shí)戰(zhàn)

    音視頻開發(fā):音頻編碼原理+采集+編碼實(shí)戰(zhàn)

    消除冗余信息,壓縮量最大,也叫有損壓縮 剔除人耳聽覺范圍外的音頻信號(hào)20Hz以下和20000Hz以上; 去除被掩蔽的音頻信號(hào),信號(hào)的遮蔽可以分為頻域遮蔽和時(shí)域遮蔽; 頻域遮蔽效應(yīng) 屏蔽70分貝以下,20HZ以下,20000HZ以上 屏蔽分貝小,頻率小的聲音 兩個(gè)頻率相近發(fā)出的聲音,

    2024年02月05日
    瀏覽(20)
  • Android 音視頻開發(fā)—MediaPlayer音頻與視頻的播放介紹

    Android 音視頻開發(fā)—MediaPlayer音頻與視頻的播放介紹

    Android多媒體中的——MediaPlayer,我們可以通過這個(gè)API來播放音頻和視頻該類是Androd多媒體框架中的一個(gè)重要組件,通過該類,我們可以以最小的步驟來獲取,解碼和播放音視頻。 它支持三種不同的媒體來源: 本地資源 內(nèi)部的URI,比如你可以通過ContentResolver來獲取 外部URL(流

    2024年02月10日
    瀏覽(27)
  • 【原理+實(shí)戰(zhàn)+視頻+源碼】抖音,快手大熱背后——Android-貼心的音視頻學(xué)習(xí)指南來咯

    【原理+實(shí)戰(zhàn)+視頻+源碼】抖音,快手大熱背后——Android-貼心的音視頻學(xué)習(xí)指南來咯

    下面將這份文檔的內(nèi)容以圖片的形式展現(xiàn)出來,但篇幅有限只能展示部分,如果你需要“高清完整的pdf版”,可以直接點(diǎn)擊我的【GitHub】即可免費(fèi)領(lǐng)取。 一、初級(jí)入門篇 初級(jí)入門篇主要是接觸Android多媒體展示相關(guān)的API, 通過單獨(dú)的列舉和使用這些API,對(duì)Android音視頻處理有

    2024年04月17日
    瀏覽(18)
  • 【原理+實(shí)戰(zhàn)+視頻+源碼】抖音,快手大熱背后——Android 貼心的音視頻學(xué)習(xí)指南來咯

    【原理+實(shí)戰(zhàn)+視頻+源碼】抖音,快手大熱背后——Android 貼心的音視頻學(xué)習(xí)指南來咯

    (三)C 與 C++之預(yù)處理命令與用 typedef 命名已有類型 JNI 模塊 JNI 開發(fā)之 靜態(tài)注冊(cè)與動(dòng)態(tài)注冊(cè)(一) JNI 開發(fā)之方法簽名與 Java 通信(二) JNI 開發(fā)之局部引用、全局引用和弱全局引用(三) 二、中級(jí)進(jìn)階篇 學(xué)習(xí) Android 平臺(tái) OpenGL ES API,了解 OpenGL 開發(fā)的基本流程,使用 OpenG

    2024年04月22日
    瀏覽(23)
  • 音視頻開發(fā)實(shí)戰(zhàn)03-FFmpeg命令行工具移植

    音視頻開發(fā)實(shí)戰(zhàn)03-FFmpeg命令行工具移植

    作為一個(gè)音視頻開發(fā)者,在日常工作中經(jīng)常會(huì)使用ffmpeg 命令來做很多事比如轉(zhuǎn)碼 ffmpeg -y -i test.mov -g 150 -s 1280x720 -codec libx265 -r 25 test_h265.mp4 ,水平翻轉(zhuǎn)視頻: ffmpeg -i src.mp4 -vf hflip -acodec copy -vcodec h264 -b 22000000 out.mp4 ,視頻截?。?ffmpeg -i input.wmv -ss 00:00:30.0 -c copy -t 00:00:10.0 ou

    2024年02月16日
    瀏覽(31)
  • 【秒懂音視頻開發(fā)】15_AAC編碼實(shí)戰(zhàn)

    【秒懂音視頻開發(fā)】15_AAC編碼實(shí)戰(zhàn)

    本文將分別通過命令行、編程2種方式進(jìn)行AAC編碼實(shí)戰(zhàn),使用的編碼庫(kù)是libfdk_aac。 fdk-aac對(duì)輸入的PCM數(shù)據(jù)是有參數(shù)要求的,如果參數(shù)不對(duì),就會(huì)出現(xiàn)以下錯(cuò)誤: 采樣格式 必須是16位整數(shù)PCM。 采樣率 支持的采樣率有(Hz): 8000、11025、12000、16000、22050、24000、32000 44100、48000、

    2024年02月03日
    瀏覽(32)
  • 音視頻開發(fā)系列(6)——全面了解Android MediaFormat

    MediaFormat 是 Android 平臺(tái)中用于描述音視頻格式的類,它提供了許多 API 用于設(shè)置和獲取音視頻的格式信息。以下是 MediaFormat 類的主要 API: 用于創(chuàng)建音頻和視頻格式的 MediaFormat 對(duì)象。需要指定媒體類型(例如 audio/mp4a-latm 或 video/avc)、媒體的采樣率、通道數(shù)、碼率、幀率等信

    2024年02月01日
    瀏覽(28)
  • Android開源計(jì)劃-一周開發(fā)app,webrtc音視頻開發(fā)

    Android開源計(jì)劃-一周開發(fā)app,webrtc音視頻開發(fā)

    題目 – 一周開發(fā)app計(jì)劃 首批參與成員 -小巫 -墨香 -夢(mèng)痕 -邊城刀客 -徐cc 要求 – -每位認(rèn)領(lǐng)者按照開源規(guī)范來做,代碼規(guī)范和Android開發(fā)規(guī)范 -每位認(rèn)領(lǐng)者必須擁有g(shù)ithub賬號(hào),熟練使用git對(duì)代碼進(jìn)來管理 -每個(gè)人認(rèn)領(lǐng)一個(gè)功能點(diǎn)或模塊 -提出完善的解決方案并提供封裝良好的庫(kù)

    2024年04月08日
    瀏覽(90)
  • 音視頻開發(fā)三:Windows環(huán)境下FFmpeg編譯安裝

    音視頻開發(fā)三:Windows環(huán)境下FFmpeg編譯安裝

    FFmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的 開源計(jì)算機(jī)程序 。采用LGPL或GPL許可證 。它提供了錄制、轉(zhuǎn)換以及流化音視頻的完整解決方案。它包含了非常先進(jìn)的音頻/視頻編解碼庫(kù)libavcodec。 FFmpeg在Linux平臺(tái)下開發(fā),但它同樣也可以在其它操作系統(tǒng)環(huán)

    2024年02月04日
    瀏覽(39)
  • 音視頻開發(fā)十七:Windows VS 2022 環(huán)境配置SDL2開發(fā)環(huán)境

    音視頻開發(fā)十七:Windows VS 2022 環(huán)境配置SDL2開發(fā)環(huán)境

    SDL(Simple DirectMedia Layer)是 一套開放源代碼的跨平臺(tái)多媒體開發(fā)庫(kù) , 使用C語(yǔ)言寫成 。能夠提供視頻渲染,音頻播放,鼠標(biāo)/鍵盤控制等操作。 跨平臺(tái)是說它對(duì)外接供了一套統(tǒng)一的接口,但在內(nèi)部, 它會(huì)根據(jù)不同平臺(tái)調(diào)用不同的底層 API庫(kù) 。如在 Linux 系統(tǒng)下,它會(huì)使用 ope

    2024年02月10日
    瀏覽(50)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包