網站首頁 編程語言 正文
前言
在之前學習如何使用MediaPlayer后,了解到Android系統提供開發者播放多媒體全家桶能力,但對于開發者希望DIY自由度更高的播放器能力也是可以利用Android內部提供組件包自行實現一個播放器的。舉例實現一個視頻播放這個流程,它大致流程是【多媒體文件解析提取視頻文件】-> 【視頻流解碼】-> 【解碼數據播放渲染到Render】。首要需要實現的是多媒體中需要文件提取工作,這就需要使用到Android提供MediaExtactor
類來實現提取媒體信息能力。
MediaExtactor
MediaExtactor
在Android
音視頻開發中負責提取音視頻信息和數據流的功能,可以通過該類實現從多媒體文件中剝離得到音頻和視頻的能力。
使用MediaExtactor
在一個音視頻文件多可能會包含多個數據流(音頻數據、視頻數據等一般情況是一個視頻組合多個音頻)
- 因此需要
MediaExtactor
加載音視頻文件獲取到所有數據軌道 - 通過遍歷獲取到想要操作的軌道
- 然后指定該軌道是
MediaExtactor
所有解析的數據流 - 通過
MediaExtactor
獲取到該軌道MediaFormat
加載音視頻文件代碼
加載音視頻文件過程可傳遞Uri
、path
、URL
等。在確認希望需要解析的數據軌道后調用selectTrack
就能鎖定當前MediaExtactor
要使用的軌道在之后數據解碼中去使用。
// 加載資源 MediaExtractor extractor = new MediaExtractor(); extractor.setDataSource(path); // 遍歷獲取視頻軌道 int trackIndex = getTrackIndex(extractor, "audio/"); // 選定軌道 extractor.selectTrack(trackIndex);
獲取軌道代碼
加載文件之后可以通過MediaExtactor
的getTrackCount
方法獲取到所有數據軌道。然后可以通過getTrackFormat
獲取到軌道信息,通過MediaFormat.KEY_MIME
得到軌道格式比對期望所有獲取到的軌道,比如比對"audio/"
就是希望獲取到音頻軌道數據。
// 獲取指定軌道的方法 private static int getTrackIndex(MediaExtractor extractor, String mediaType) { int trackIndex = -1; for (int i = 0; i < extractor.getTrackCount(); i++) { MediaFormat mediaFormat = extractor.getTrackFormat(i); String mime = mediaFormat.getString(MediaFormat.KEY_MIME); if (mime.startsWith(mediaType)) { trackIndex = i; break; } } return trackIndex; }
提取軌道數據信息
在選定希望獲取到的軌道后就可以獲取到當前選擇軌道的基本信息,例如視頻尺寸大小、格式、時長、碼率等一些音視頻相關基礎信息方便只有做解碼時選用合適的解碼器以及其他必要信息確認。
音頻軌道基礎信息獲取
MediaFormatInfo mediaFormatInfo = new MediaFormatInfo(); mediaFormatInfo.mediaFormat = mediaFormat; mediaFormatInfo.audioChannels = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT); mediaFormatInfo.audioSampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE); mediaFormatInfo.maxInputSize = mediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); mediaFormatInfo.mime = mediaFormat.getString(MediaFormat.KEY_MIME);
視頻軌道基礎信息獲取
MediaFormatInfo mediaFormatInfo = new MediaFormatInfo(); mediaFormatInfo.mediaFormat = mediaFormat; mediaFormatInfo.videoHeight = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT); mediaFormatInfo.videoWidth = mediaFormat.getInteger(MediaFormat.KEY_WIDTH); mediaFormatInfo.timeDuration = mediaFormat.getLong(MediaFormat.KEY_DURATION); mediaFormatInfo.mime = mediaFormat.getString(MediaFormat.KEY_MIME);
但如果你選取的軌道是視頻軌道但操作錯誤提取了音頻相關信息可能會出現錯誤崩潰的情況(例如KEY_IS_ADTS
只有音頻軌道才能提取),因此盡量保證提取參數是否正確做好代碼保護機制。
一些源碼細節分析
MediaExtactor
作為提取器,其底層代碼邏輯也是調用JNI來實現的,它只是上層API提供出能力而已。 在源碼細節中可以看到MediaExtactor
同樣是加載media_jni
so庫,這和MediaPlayer
是一樣的邏輯。
public MediaExtractor() { native_setup(); } private native final void native_setup(); static { System.loadLibrary("media_jni"); native_init(); }
同時setDataSoure
方法調用底層native
接口和MediaPlayer
也是同樣的方法名和入參。
private native final void nativeSetDataSource( @NonNull IBinder httpServiceBinder, @NonNull String path, @Nullable String[] keys, @Nullable String[] values) throws IOException;
這基本也能夠了解MediaExtactor
和MediaPlayer
在底層實現上應該屬于同一套邏輯和功能。只不過MediaExtactor
可以理解為MediaPlayer
其中一小部分功能提供提取能力而MediaPlayer
是封裝成型的工具類只需要加載音視頻資源文件播放即可,中間提取軌道和解析過程直接就在底層幫開發者實現了。
原文鏈接:https://juejin.cn/post/7090477876813758471
- 上一篇:深度解析Python線程和進程_python
- 下一篇:iOS自定義滑桿效果_IOS
相關推薦
- 2023-06-17 C#中Stopwatch的使用及說明_C#教程
- 2022-10-20 C++淺析虛函數使用方法_C 語言
- 2022-09-23 Android?創建AIDL文件使用教程_Android
- 2022-04-24 Android掛斷電話最新實現方法_Android
- 2022-08-10 讀取Go項目中的配置文件的方法_Golang
- 2022-04-22 SketchUp:解決鏡頭剪切屏幕出現破面視角的問題圖文教程
- 2022-10-08 C#中Timer實現Tick使用精度的問題_C#教程
- 2023-04-23 Go之接口型函數用法_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支