音視頻 五 看書的筆記 MediaCodec

MediaCodec

用于訪問底層媒體編解碼器框架,編解碼組件。通常與MediaExtractor(解封裝,例如Mp4文件分解成 video和audio)、MediaSync、MediaMuxer(封裝 例如音視頻合成Mp4文件)、MediaCrypto、Image(cameraX 回調的ImageReader對象可以獲取到Image幀圖像,可轉換成YUV420數組,傳遞給編碼器編碼),Surface(camera的預覽回調)、Audio一起使用。
在這里插入圖片描述

創建MediaCodec

    public static MediaCodec createEncoderByType(@NonNull String type)  //創建編碼器public static MediaCodec createDecoderByType(@NonNull String type) //創建解碼器

一般type是:

  • h264 MediaFormat.MIMETYPE_VIDEO_AVC(video/avc)
  • h265 MediaFormat.MIMETYPE_VIDEO_HEVC(video/hevc)
   public static MediaCodec createByCodecName(@NonNull String name) //通過名稱創建

一般name是:

  • OMX.google.h264.encoder 軟編碼
  • OMX.google.h264.decoder 軟解碼
  • OMX.MTK.VIDEO.DECODER.AVC 硬解碼

  • 以下代碼可以檢測是否支持某編解碼
MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
for (MediaCodecInfo codecInfo : codecList.getCodecInfos()) {if (codecInfo.isEncoder()) {continue; // 只檢查解碼器}String[] types = codecInfo.getSupportedTypes();for (String type : types) {if (type.equalsIgnoreCase("video/hevc")) {Log.d("MediaCodec", "Device supports H265 decoding");return; // 找到支持的解碼器,可以退出}}
}
Log.d("MediaCodec", "Device does not support H265 decoding");

工作方式

以以下代碼為例

// 假設你已經有了ByteBuffer data和BufferInfo info
codec.queueInputBuffer(inputBufferIndex, 0, data.limit(), presentationTimeUs, 0);
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 10000);
while (outputBufferIndex >= 0) {// 處理輸出幀,例如繪制到Surface或保存到文件等codec.releaseOutputBuffer(outputBufferIndex, true); // true表示將輸出幀渲染到Surface中(如果有的話)outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 0); // 再次嘗試獲取下一個輸出幀
}
  • queueInputBuffer 處理輸入數據(如:camera/cameraX回調的視頻幀數據)
  • dequeueOutputBuffer 輸出數據 編碼后的數據(如:使用H264編碼則 可直接將數據保存為H264文件)
    分析:
  • MediaCodeC使用一組輸入和輸出Buffer隊列。
  • 數據填入設定的空輸入緩沖區 ( inputBuffers = mediaCodec.getInputBuffers();),填滿數據后傳遞給MediaCodec進行編解碼
  • 編解碼后數據填充到一個輸出Buffer中。

狀態

  • MediaCodec 有三種狀態 Stopped Executing Released
    – Stopped 包括 三種狀態 Uninitialized Configured Error
    – Executing 包括三種狀態 Flushed Running End-of-Stream

狀態

  • 通過以上create工廠方法創建一個MediaCodec ,MediaCodec 處于未初始化狀態
  • 需要通過MediaCodec對象的configure方法配置,配置后 處于配置狀態
String mimeType = "video/hevc"; // H265 MIME類型
MediaCodec codec = MediaCodec.createDecoderByType(mimeType);
MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); // 使用Surface作為輸出類型,如果是預覽或顯示使用
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); // 設置比特率,如果需要的話
format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate); // 設置幀率,如果需要的話
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 設置I幀間隔,通常設置為1或2codec.configure(format, null, null, 0); // 使用null作為輸出Surface,因為我們不直接處理輸出數據
codec.start();
  • 調用start之后 處于 Executing狀態
  • 調用start后,MediaCodec 會立刻刷新子狀態(Flushed ) 并擁有所有的Buffer
  • 第一個輸入Buffer從隊列中移除 MediaCodec 會花較長時間轉換為 正在運行的子狀態 (Running )
  • 當隊列輸入Buffer攜帶End-of-Stream標記 則轉換為 End-of-Stream子狀態 這種狀態MediaCodec不再接收輸入Buffer,但是仍然會產生輸出Buffer
  • Executing狀態下,調用flush函數可以回到 Flushed子狀態
  • 調用stop,MediaCodec 處于Uninitialized 狀態 等待再次配置和使用
  • 再次創建MediaCodec 時,上個MediaCodec 對象必須調用release函數
  • 極少數情況會出現Error狀態,此時需要調用reset函數讓MediaCodec 再次可用

MediaCodec 從創建到start的過程

  • 需要經歷JNI
  • 與MediaPlayer有很多相似的地方
  • 我幫大家看了 想看的花去點這里

就是MediaCodec 會對應到 c++層的JMediaCodec方法
release -> native_release
reset -> native_reset
setup -> native_setup
finalize -> native_finalize
config -> native_configure

  • setup -> 調用 JMediaCodec 構造方法創建JMediaCodec
  • JMediaCodec的構造方法 -> createByType/CreateByComponentName 創建JMediaCodec
  • 接著java 調用config -> native_configure
  • native_configure -> 獲取前邊創建的JMediaCodec 對象 調用其configure方法 構建編解碼器
  • java 層調用 start -> 最終使用的還是JMediaCodec 對象 的 start方法 會直行ACodec.cpp 的start 函數

MediaCodec 到OMX過程

OpenMAX Integration Layer(OMX IL,集成層)是由Khronos Group開發的一套低層級標準接口,旨在為編解碼器提供一定程度的抽象,使得嵌入式或移動設備能夠統一調用音頻、視頻和圖像編解碼器,從而實現編解碼器實現代碼和調用代碼的跨平臺性。
OMX IL API由兩大主要部分組成,分別是Core API和Component API。
OMX IL Component:在OMX IL中組件表示獨立的功能模塊,組件可能是source(源)、sinks(接收器)、codecs(編解碼器)、filters(過濾器)或任何其他數據處理模塊,組件需要依據Component API來實現。與組件之間的數據通信是通過稱為端口的接口進行的,用戶可以通過輸入端口向組件發送數據,也可以通過輸出端口接收數據。
OMX IL Core:Core API主要用于動態加載卸載組件,調用組件方法;
將OMX IL API封裝并向上層提供高層級接口的部分被稱為IL Client(客戶端),IL Client使用OMX Core來加載組件,卸載組件,調用組件的方法。

  • MediaCodec::init 函數
    – 創建Acodec Acodec繼承AHander(消息機制有了)
    – 初始化ALooper AMessage
    – 發送kWhatInit消息
    – ACodec收到消息 調用initiateAllocateComponent(format)函數
    – 發送kWhatAllocateComponent消息
  • 消息中心收到消息 調用onAllocateComponent回調函數
    – 通過ACodec::AllocateComponent函數判斷OMXClient和Server是否正常建立連接
    – 通過IOMX進行IPC通信
    – 調用omx->allocateNode分配Node節點
  • onConfigureComponent 函數
    – 調用ACodec的configCodec函數 構建編解碼器

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75686.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75686.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75686.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

李宏毅NLP-3-語音識別part2-LAS

語音識別part2——LAS Listen Listen主要功能是提取內容信息,去除說話人差異和噪聲 。編碼器(Encoder)結構,輸入是聲學特征,經過 Encoder 處理后,輸出為高級表示,這些高級表示可用于后續語音識別…

開源CMS的模塊化設計和API接口如何具體影響其擴展性?

優秀的CMS系統都有自己主打的特點,開源CMS憑借其靈活性和低成本優勢占據了市場主流地位,而模塊化設計與API接口正是其擴展性的兩大基石。本文將深入探討這兩大技術特性是如何影響cms的擴展性的。 一、模塊化設計:功能解耦與生態繁榮的引擎 …

一文讀懂WPF系列之常用控件以及樣式

WPF控件 控件分類概覽常用控件常用控件代碼示例和效果 樣式與模板應用樣式定義??方式行內樣式??頁面/窗口級資源樣式(Local Resource)應用程序全局資源獨立資源字典(ResourceDictionary)控件模板(ControlTemplate&…

AndroidTV D貝桌面-v3.2.5-[支持文件傳輸]

AndroidTV D貝桌面 鏈接:https://pan.xunlei.com/s/VONXSBtgn8S_BsZxzjH_mHlAA1?pwdzet2# AndroidTV D貝桌面-v3.2.5[支持文件傳輸] 第一次使用的話,壁紙默認去掉的,不需要按遙控器上鍵,自己更換壁紙即可

XDocument和XmlDocument的區別及用法

因為這幾天用到了不熟悉的xml統計數據,啃了網上的資料解決了問題,故總結下xml知識。 1.什么是XML?2.XDocument和XmlDocument的區別3.XDocument示例1示例2:示例3: 4.XmlDocument5.LINQ to XML6.XML序列化(Serialize)與反序列化(De…

從競速到巡檢:不同無人機如何匹配最佳PCB方案?

隨著無人機技術的快速發展,高性能PCB(印刷電路板)成為無人機制造商的核心需求之一。無論是消費級無人機還是工業級應用,PCB的質量直接影響飛行控制、信號傳輸和整機穩定性。那么,無人機制造商在選型高端PCB時&#xff…

高支模自動化監測解決方案

1.行業現狀 高大模板支撐系統在澆筑施工過程中,諸多重大安全風險點進行實時自動化安全監測的解決方案主要監測由于頂桿失穩、扣件失效、承壓過大等引起的支撐軸力、模板沉降、相對位移、支撐體系傾斜等參數變化。系統采用無線自動組網、高頻連續采樣,實時…

python【標準庫】multiprocessing

文章目錄 介紹多進程Process 創建子進程共享內存數據多進程通信Pool創建子進程多進程案例多進程注意事項介紹 python3.10.17版本multiprocessing 是一個多進程標準模塊,使用類似于threading模塊的API創建子進程,充分利用多核CPU來并行處理任務。提供本地、遠程的并發,高效避…

UniApp基于xe-upload實現文件上傳組件

xe-upload地址:文件選擇、文件上傳組件(圖片,視頻,文件等) - DCloud 插件市場 致敬開發者!!! 感覺好用的話,給xe-upload的作者一個好評 背景:開發中經常會有…

STM32 HAL庫之GPIO示例代碼

LED燈不斷閃爍 GPIO初始化,main文件中的 MX_GPIO_Init(); 也就是在 gpio.c文件中 void MX_GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOE_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOA_C…

二維數點 系列 題解

1.AT_dp_w Intervals 我的博客 2.CF377D Developing Games 我的博客 這兩道題是比較經典的線段樹區間 trick,希望自己可以在以后的比賽中手切。 3.洛谷 P10814 離線二維數點 題意 給你一個長為 n n n 的序列 a a a,有 m m m 次詢問&#xff0c…

vulkanscenegraph顯示傾斜模型(5.9)-vsg中vulkan資源的編譯

前言 上一章深入剖析了GPU資源內存及其管理,vsg中為了提高設備內存的利用率,同時減少內存(GPU)碎片,采用GPU資源內存池機制(vsg::MemoryBufferPools)管理邏輯緩存(VkBuffer)與物理內存(VkDeviceMemory)。本章將深入vsg中vulkan資源的編譯(包含…

探秘 Python 網絡編程:構建簡單聊天服務器

在計算機網絡的世界里,網絡編程是實現不同設備之間通信的關鍵技術。Python 憑借其簡潔的語法和強大的庫支持,在網絡編程領域有著廣泛的應用。無論是構建簡單的聊天服務器,還是開發復雜的網絡應用,Python 都能輕松勝任。 1 理論基礎…

Go語言Slice切片底層

Go語言(Golang)中切片(slice)的相關知識、包括切片與數組的關系、底層結構、擴容機制、以及切片在函數傳遞、截取、增刪元素、拷貝等操作中的特性。并給出了相關代碼示例和一道面試題。關鍵要點包括: 數組特性&#xf…

vue3 ts 自定義指令 app.directive

在 Vue 3 中,app.directive 是一個全局 API,用于注冊或獲取全局自定義指令。以下是關于 app.directive 的詳細說明和使用方法 app.directive 用于定義全局指令,這些指令可以用于直接操作 DOM 元素。自定義指令在 Vue 3 中非常強大&#xff0…

基于python的機器學習(五)—— 聚類(二)

一、k-medoids聚類算法 k-medoids是一種聚類算法,它是基于k-means聚類算法的一種改進。k-medoids算法也是一種迭代算法,但是它將中心點限定為數據集中的實際樣本點,而不是任意的點。 具體來說,k-medoids算法從數據集中選擇k個初…

解釋:指數加權移動平均(EWMA)

指數加權移動平均(EWMA, Exponential Weighted Moving Average) 是一種常用于時間序列平滑、異常檢測、過程控制等領域的統計方法。相比普通移動平均,它對最近的數據賦予更高權重,對舊數據逐漸“淡化”。 ? 一、通俗理解 想象你…

Spring Boot 項目基于責任鏈模式實現復雜接口的解耦和動態編排!

全文目錄: 開篇語前言一、責任鏈模式概述責任鏈模式的組成部分: 二、責任鏈模式的核心優勢三、使用責任鏈模式解耦復雜接口1. 定義 Handler 接口2. 實現具體的 Handler3. 創建訂單對象4. 在 Spring Boot 中使用責任鏈模式5. 配置責任鏈6. 客戶端調用 四、…

COMSOL仿真遇到的兩個小問題

最近跑熱仿真的時候跑出了兩個問題,上網查發現也沒什么解決方式,最后自己誤打誤撞的摸索著解決了,在這里分享一下。 問題一 我當時一準備跑仿真就彈出了這個東西,但在此之前從未遇到 然后我試著在它說的路徑中建立recoveries文件…

如何在英文學術寫作中正確使用標點符號?

標點符號看似微不足道,但它們是書面語言的無名英雄。就像熟練的指揮家指揮管弦樂隊一樣,標點符號可以確保您的寫作流暢、傳達正確的含義并引起讀者的共鳴。正如放錯位置的音符會在音樂中造成不和諧一樣,放錯位置的逗號或缺少分號也會使您的寫…