Linux驅動25 --- RkMedia音頻API使用增加 USB 音視頻設備

目錄

一、RV1126 增加 USB 音視頻設備

二、RkMedia 音頻 API

2.1 PCM 音頻輸入

????????系統初始化

????????AI 通道配置

????????AI 通道使能

????????開啟數據流

????????獲取數據

????????保存數據

2.2 編碼音頻編碼輸入

2.3 PCM 音頻輸出


一、RV1126 增加 USB 音視頻設備

配置過程

????????第一步:來到 SDK 內核路徑下

????????source envsetup.sh --- 選擇:rockchip_rv1126_rv1109_spi_nand 選項

????????./build.sh lunch --- 選擇:BoardConfig-38x38-spi-nand.mk 選項

????????cd kernel

????????make ARCH=arm rv1126_defconfig

????????make ARCH=arm menuconfig

USB 攝像頭支持

Device Drivers --->

????????<*> Multimedia support --->

????????????????[*] Media USB Adapters --->

????????????????????????<*> USB Video Class (UVC)

????????????????????????????????[*] UVC input events device support

USB 音頻

Device Drivers --->

????????<*> Sound card support --->

????????????????<*> Advanced Linux Sound Architecture --->

????????????????????????[*] USB sound devices --->

????????????????????????????????<*> USB Audio/MIDI driver

保存退出

????????make ARCH=arm savedefconfig

????????cp defconfig arch/arm/configs/rv1126_defconfig

????????編譯固件然后燒錄

使用

查看聲音輸出設備

????????aplay -l

????????當前 USB 聲卡為 card1

????????所以執行的指令為:

????????aplay -D plughw:1,0 /sdcard/1.wav

查看聲音輸入設備

arecord -l

查看視頻輸入設備

v4l2-ctl --list-devices

官方音頻測試例程

????????SDK/buildroot/output/rockchip_rv1126_rv1109/build/rkmedia/examples

????????????????rkmedia_audio_test.c

像編譯自己寫的程序一樣編譯即可

編譯內核紅色的警告

這個是正常的,是 SDK 提醒不要隨便改電源配置

二、RkMedia 音頻 API

核心:音頻

2.1 PCM 音頻輸入

????????系統初始化

????????????????RK_MPI_SYS_Init();

????????AI 通道配置

????????????????RK_MPI_AI_SetChnAttr(0, &ai_attr);

????????AI 通道使能

????????????????RK_MPI_AI_EnableChn(0);

????????開啟數據流

????????????????RK_MPI_AI_StartStream(0);

????????獲取數據

????????保存數據

arecord -L

????????播放 PCM 的指令

????????aplay -f S16_LE -r 48000 -c 2 9203.pcm

2.2 編碼音頻編碼輸入

????????MP2

????????????????用于和 H264 視頻共同合成一個 mp4 文件

????????G711A

????????????????用于音頻推流 --- rkmedia 不支持推太大的數據流

????????????????編碼后的文件是無法播放的

????????后續 MP2 在合成的音視頻中可以播放

????????G711A 可以推流之后在 VLC 播放

????????RV1126板子可以做的音頻解碼

????????????????可以做 G711A 的解碼

????????編碼和 PCM 多的內容在

????????????????創建一個編碼通道

????????????????做一個綁定

2.3 PCM 音頻輸出

????????主要使用的是 AO 通道

????????AI --- 音頻輸入設置的參數

????????????????為了保存數據

????????AO --- 音頻輸出設置的參數

????????????????為了準確無誤的獲取參數

????????AO 的參數要和 AI 的參數保持一致

RK_MPI_SYS_Init();RK_MPI_AO_SetChnAttr(0, &ao_attr);RK_MPI_AO_EnableChn(0);//計算延時時間RK_U32 u32Timeval = u32FrameCnt * 1000000 / u32SampleRate; // usMB_AUDIO_INFO_S stSampleInfo = {ao_attr.u32Channels,ao_attr.u32SampleRate,ao_attr.u32NbSamples, ao_attr.enSampleFormat
};mb = RK_MPI_MB_CreateAudioBufferExt(&stSampleInfo, RK_FALSE, 0);fread(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), file);RK_MPI_SYS_SendMediaBuffer(RK_ID_AO, 0, mb);usleep(u32Timeval);RK_MPI_MB_ReleaseBuffer(mb);mb = NULL; 

?????????aplay -L

代碼

mp2_aenc

#include "main.h"
#include <time.h>RK_U32 ai_chn = 2;      //于G711A編碼格式給1
RK_U32 nbsmp = 1152;    //對于MP2編碼格式給1152,對于G711A編碼格式給1024
RK_U32 srate = 48000;   //PCM格式,不要太低,G711A編碼格式給8000
int end_flag = 0;
FILE *file;// 輸出回調函數
void myoutcbfunc(MEDIA_BUFFER mb) 
{if(end_flag){RK_MPI_MB_ReleaseBuffer(mb);return;}fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), file);RK_MPI_MB_ReleaseBuffer(mb);}int main(void)
{//PCM音頻輸入file = fopen("./9203.mp2", "w");//1.系統初始化RK_MPI_SYS_Init();//2.AI通道配置AI_CHN_ATTR_S ai_pstAttr = {0};ai_pstAttr.enAiLayout = AI_LAYOUT_NORMAL;ai_pstAttr.enSampleFormat = RK_SAMPLE_FMT_S16;ai_pstAttr.pcAudioNode = "default:CARD=Device";ai_pstAttr.u32Channels = ai_chn;                            //于G711A編碼格式給1ai_pstAttr.u32NbSamples = nbsmp;     //對于MP2編碼格式給1152,對于G711A編碼格式給1024ai_pstAttr.u32SampleRate = srate;    //PCM格式,不要太低,G711A編碼格式給8000RK_MPI_AI_SetChnAttr(0, &ai_pstAttr);//AI通道使能RK_MPI_AI_EnableChn(0);//開啟數據流  RK_MPI_AI_StartStream(0);//獲取數據MPP_CHN_S ai_pstChn = {0};ai_pstChn.enModId = RK_ID_AI;//視頻輸入通道ai_pstChn.s32ChnId = 0;//VI通道ai_pstChn.s32DevId = 0;RK_MPI_SYS_RegisterOutCb(&ai_pstChn, myoutcbfunc);int count = 10;while(1){sleep(1);if(!count){end_flag = 1;break;}printf("剩余 %d 秒結束\n", count);count--;}fclose(file);RK_MPI_AI_DisableChn(0);//保存數據return 0;
}

g711a_aenc

#include "main.h"
#include <time.h>RK_U32 ai_chn = 1;      //mp2給2, 于G711A編碼格式給1
RK_U32 nbsmp = 1024;    //對于MP2編碼格式給1152,對于G711A編碼格式給1024
RK_U32 srate = 8000;   //PCM格式,不要太低,G711A編碼格式給8000
int end_flag = 0;
FILE *file;// 輸出回調函數
void myoutcbfunc(MEDIA_BUFFER mb) 
{if(end_flag){RK_MPI_MB_ReleaseBuffer(mb);return;}fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), file);RK_MPI_MB_ReleaseBuffer(mb);}int main(void)
{//PCM音頻輸入//file = fopen("./9203.mp2", "w");file = fopen("./9203.g711a", "w");//1.系統初始化RK_MPI_SYS_Init();//2.AI通道配置AI_CHN_ATTR_S ai_pstAttr = {0};ai_pstAttr.enAiLayout = AI_LAYOUT_NORMAL;ai_pstAttr.enSampleFormat = RK_SAMPLE_FMT_S16;ai_pstAttr.pcAudioNode = "default:CARD=Device";ai_pstAttr.u32Channels = ai_chn;                            //于G711A編碼格式給1ai_pstAttr.u32NbSamples = nbsmp;     //對于MP2編碼格式給1152,對于G711A編碼格式給1024ai_pstAttr.u32SampleRate = srate;    //PCM格式,不要太低,G711A編碼格式給8000RK_MPI_AI_SetChnAttr(0, &ai_pstAttr);//AI通道使能RK_MPI_AI_EnableChn(0);//開啟數據流  RK_MPI_AI_StartStream(0);AENC_CHN_ATTR_S aenc_pstAttr = {0};// aenc_pstAttr.enCodecType = RK_CODEC_TYPE_MP2;// aenc_pstAttr.stAencMP2.u32Channels = ai_chn;// aenc_pstAttr.stAencMP2.u32SampleRate = srate;aenc_pstAttr.enCodecType = RK_CODEC_TYPE_G711A;aenc_pstAttr.stAencG711A.u32Channels = ai_chn;aenc_pstAttr.stAencG711A.u32NbSample = nbsmp;aenc_pstAttr.stAencG711A.u32SampleRate = srate;aenc_pstAttr.u32Bitrate = 64000; //嚴格來說,這個需要算aenc_pstAttr.u32Quality = 1;RK_MPI_AENC_CreateChn(0, &aenc_pstAttr);    //在此創建一個通道 --- 演示編碼MP2編碼(音視頻合成)和G711A的編碼(推流) --- AI0綁定AENC0,AI0綁定AENC1MPP_CHN_S a_pstSrcChn = {0};a_pstSrcChn.enModId = RK_ID_AI;a_pstSrcChn.s32ChnId = 0;a_pstSrcChn.s32DevId = 0;MPP_CHN_S a_pstDestChn = {0};a_pstDestChn.enModId = RK_ID_AENC;    //后續AENC的通道ID是需要改的a_pstDestChn.s32ChnId = 0;a_pstDestChn.s32DevId = 0;RK_MPI_SYS_Bind(&a_pstSrcChn, &a_pstDestChn);RK_MPI_SYS_RegisterOutCb(&a_pstDestChn, myoutcbfunc);int count = 10;while(1){sleep(1);if(!count){end_flag = 1;break;}printf("剩余 %d 秒結束\n", count);count--;}fclose(file);RK_MPI_SYS_UnBind(&a_pstSrcChn, &a_pstDestChn);RK_MPI_AENC_DestroyChn(0);RK_MPI_AI_DisableChn(0);//保存數據return 0;
}

ai_pcm

#include "main.h"
#include <time.h>RK_U32 ai_chn = 2;      //于G711A編碼格式給1
RK_U32 nbsmp = 1152;    //對于MP2編碼格式給1152,對于G711A編碼格式給1024
RK_U32 srate = 48000;   //PCM格式,不要太低,G711A編碼格式給8000
int end_flag = 0;
FILE *file;// 輸出回調函數
void myoutcbfunc(MEDIA_BUFFER mb) 
{if(end_flag){RK_MPI_MB_ReleaseBuffer(mb);return;}fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), file);RK_MPI_MB_ReleaseBuffer(mb);}int main(void)
{//PCM音頻輸入file = fopen("./9203.pcm", "w");//1.系統初始化RK_MPI_SYS_Init();//2.AI通道配置AI_CHN_ATTR_S ai_pstAttr = {0};ai_pstAttr.enAiLayout = AI_LAYOUT_NORMAL;ai_pstAttr.enSampleFormat = RK_SAMPLE_FMT_S16;ai_pstAttr.pcAudioNode = "default:CARD=Device";ai_pstAttr.u32Channels = ai_chn;                            //于G711A編碼格式給1ai_pstAttr.u32NbSamples = nbsmp;     //對于MP2編碼格式給1152,對于G711A編碼格式給1024ai_pstAttr.u32SampleRate = srate;    //PCM格式,不要太低,G711A編碼格式給8000RK_MPI_AI_SetChnAttr(0, &ai_pstAttr);//AI通道使能RK_MPI_AI_EnableChn(0);//開啟數據流  RK_MPI_AI_StartStream(0);//獲取數據MPP_CHN_S ai_pstChn = {0};ai_pstChn.enModId = RK_ID_AI;//視頻輸入通道ai_pstChn.s32ChnId = 0;//VI通道ai_pstChn.s32DevId = 0;RK_MPI_SYS_RegisterOutCb(&ai_pstChn, myoutcbfunc);int count = 10;while(1){sleep(1);if(!count){end_flag = 1;break;}printf("剩余 %d 秒結束\n", count);count--;}fclose(file);RK_MPI_AI_DisableChn(0);//保存數據return 0;
}

ao_pcm

#include "main.h"
#include <time.h>RK_U32 ai_chn = 2;      //mp2給2, 于G711A編碼格式給1
RK_U32 nbsmp = 1152;    //對于MP2編碼格式給1152,對于G711A編碼格式給1024
RK_U32 srate = 48000;   //PCM格式,不要太低,G711A編碼格式給8000FILE *file;int main(void)
{file = fopen("./9203.pcm", "r");RK_MPI_SYS_Init();//1.設置AO通道屬性AO_CHN_ATTR_S ao_pstAttr = {0};ao_pstAttr.enSampleFormat = RK_SAMPLE_FMT_S16;ao_pstAttr.pcAudioNode = "default:CARD=rockchipi2s0sou";ao_pstAttr.u32Channels = ai_chn;ao_pstAttr.u32NbSamples = nbsmp;ao_pstAttr.u32SampleRate = srate;RK_MPI_AO_SetChnAttr(0, &ao_pstAttr);//2.設置AO通道RK_MPI_AO_EnableChn(0);//3.計算延時時間RK_U32 u32Timeval = nbsmp * 1000000 / srate; // us//4.填充核心結構體MB_AUDIO_INFO_S stSampleInfo = {ao_pstAttr.u32Channels, ao_pstAttr.u32SampleRate,ao_pstAttr.u32NbSamples, ao_pstAttr.enSampleFormat};//5.創建Media BufferMEDIA_BUFFER mb = NULL;int ret = 0;    //結束標志while(1){mb = RK_MPI_MB_CreateAudioBufferExt(&stSampleInfo, RK_FALSE, 0);//6.讀取一幀數據ret = fread(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), file);if(ret <= 0){break;}//7.發送給AO通道RK_MPI_SYS_SendMediaBuffer(RK_ID_AO, 0, mb);//8.延時usleep(u32Timeval);RK_MPI_MB_ReleaseBuffer(mb);mb = NULL;}RK_MPI_MB_ReleaseBuffer(mb);mb = NULL;fclose(file);RK_MPI_AENC_DestroyChn(0);//保存數據return 0;
}

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

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

相關文章

CETOL 6σ 幫助提升活檢器械精度并降低制造成本

某全球醫療器械企業采用 Sigmetrix 的 CETOL 6σ 公差分析軟件&#xff0c;針對一次性活檢采集器械&#xff08;Biopsy Harvesting Instrument&#xff09;完成結構優化&#xff0c;成功解決頜骨動力學缺陷、4mm孔徑精度控制及線纜傳動敏感度等核心挑戰&#xff0c;大大提高了活…

基于協同過濾算法的圖書推薦系統設計與實現/基于python的圖書推薦系統設計與實現/基于python的圖書借閱系統設計與實現

基于協同過濾算法的圖書推薦系統設計與實現采用django、vue技術用戶&#xff1a;注冊、登錄、圖書信息、公告信息、個人中心、借閱記錄、歸還記錄、我的收藏。管理員&#xff1a;登錄、用戶、圖書分類、圖書信息、借閱記錄、歸還記錄、系統管理、用戶信息。

線程組和線程池的基本用法

1.線程組1.1創建線程組的方法public class xianchengzu {public static void main(String[] args) {ThreadGroup group new ThreadGroup("group");// 創建線程組時指定父線程組ThreadGroup parent new ThreadGroup("parent");ThreadGroup child new Thr…

百度華為硬件筆試機試題-卷4

百度華為硬件筆試機試題-卷4 收集整理了以下30道選擇題和判斷題,涵蓋電源管理、功率放大、半導體器件、數字邏輯、信號處理和電磁理論等領域。題目涉及復雜計算和分析,給出了參考答案和詳細的解析,非常適合硬件工程師筆試機試準備。 選擇題 1. 電源紋波主要測量什么值? …

38-TS之類型保護

關注大師不迷路,大師帶你上高度~ 文章目錄 前言 一、類型保護是什么? 二、使用步驟 1. 使用 typeof 操作符 2. 使用 instanceof 操作符 3. 自定義類型保護函數 4. 使用 in 操作符 總結 前言 關注大師不迷路,大師帶你上高度~ 在前端開發中,JavaScript 的動態類型特性提供了…

win下安裝labelimg

1、anconda安裝python、qt的版本 conda create -n labelme python3.10.18 PyQt5 5.15.11 <pip> PyQt5-Qt5 5.15.2 <pip> PyQt5_sip 12.17.0 <p…

【Qt開發】常用控件(二) -> enabled

目錄 1 -> 什么是 enabled 屬性 2 -> API 3 -> 代碼示例 3.1 -> 創建禁用狀態按鈕 3.2 -> 通過按鈕切換按鈕的禁用狀態 1 -> 什么是 enabled 屬性 在 Qt 中&#xff0c;enabled 是 QWidget 類的一個基礎屬性&#xff0c;它控制控件是否對用戶輸入做出響…

MySQL 配置性能優化賽:核心策略與實戰技巧

在數據庫性能優化領域,MySQL 配置調優如同一場精密的競技比賽 —— 既要深刻理解數據庫內核機制,又要根據硬件環境和業務場景靈活調整參數,最終在性能指標上脫穎而出。本文將圍繞 MySQL 配置性能優化的核心維度,解析關鍵參數調優策略與實戰經驗。 一、性能優化的底層邏輯:…

C++ WonderTrader源碼分析之自旋鎖實現

一、介紹 在WonderTrader的文件SpinMutex.hpp定義了跨平臺的自旋鎖的實現。 二、實現原理 1、類 SpinMutex&#xff1a;自旋鎖實現SpinMutex 是一個輕量級的自旋鎖&#xff08;Spinlock&#xff09;實現&#xff0c;用于多線程之間保護臨界區資源。自旋鎖通過不斷嘗試獲取鎖而不…

【AI大模型】Spring AI 基于Redis實現對話持久存儲詳解

目錄 一、前言 二、Spring AI 會話記憶介紹 2.1 Spring AI 會話記憶概述 2.2 常用的會話記憶實現方式 2.2.1 集成數據庫持久存儲會話實現步驟 2.3 適用場景 三、Spring AI基于內存會話記憶存儲 3.1 本地開發環境準備 3.2 工程搭建與集成 3.2.1 添加核心依賴 3.3.2 添…

Numpy科學計算與數據分析:Numpy數據分析與圖像處理入門

Numpy實戰&#xff1a;從數據分析到圖像處理 學習目標 通過本課程&#xff0c;學員將學會運用Numpy庫進行數據分析和圖像處理。學習如何使用Numpy進行數據的高效處理&#xff0c;以及如何利用Numpy進行基本的圖像操作。 相關知識點 Numpy的數據分析和圖像處理 學習內容 1…

Vue框架總結案例

目錄 一、驗證用戶名是否已經被注冊過 二、過濾器 三、圖書管理系統 四、axios網絡請求 一、驗證用戶名是否已經被注冊過 1.案例 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><script src"j…

hyper-v虛擬機啟動失敗:Virtual Pci Express Port無法打開電源,因為發生錯誤,找不到即插即用設備

啟動錯誤 今天啟動某個hyper-v虛擬機時&#xff0c;啟動失敗了&#xff0c;大概的錯誤信息為&#xff1a;嘗試更改“ubuntu_desktop_2204”的狀態時應用程序遇到錯誤。Virtual Pci Express Port (實例 ID 0445948B-C377-4912-AEEB-58A3D45C5694): 無法開機&#xff0c;因…

CSS包含塊與百分比取值機制完全指南

引言&#xff1a;為什么需要理解包含塊&#xff1f; 在CSS布局的世界中&#xff0c;包含塊(Containing Block) 是一個基礎但至關重要的概念。它就像是一個隱形的參考框架&#xff0c;決定了元素如何定位、尺寸如何計算以及百分比值如何解析。許多CSS開發者在使用百分比單位時遇…

Numpy科學計算與數據分析:Numpy數組操作入門:合并、分割與重塑

Numpy數組操作實戰 學習目標 通過本課程的學習&#xff0c;學員將掌握Numpy中數組的基本操作&#xff0c;包括數組的合并、分割以及重塑等技巧&#xff0c;能夠靈活運用這些操作處理數據&#xff0c;為后續的科學計算和數據分析打下堅實的基礎。 相關知識點 Numpy數組操作 …

11_Mybatis 是如何進行DO類和數據庫字段的映射的?

11_Mybatis 是如何進行DO類和數據庫字段的映射的&#xff1f; 假設 VideoAbnormalContentMapper.xml 文件有如下方法&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN&quo…

2025年滲透測試面試題總結-06(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 邏輯漏洞 一、三大高危業務邏輯漏洞及修復方案 1. 訂單金額篡改&#xff08;參數操縱&#xff09; 2. 重…

SpringBoot激活指定profile的方式

題目詳細答案在 Spring Boot 中&#xff0c;可以通過多種方式激活指定的 Profile&#xff0c;以便在不同的環境中使用不同的配置。在application.properties文件中激活可以在默認的application.properties文件中通過spring.profiles.active屬性激活某個 Profile。# application…

Pytest項目_day10(接口的參數傳遞)

接口的參數傳遞 如果我們需要在一個測試用例中使用另一個測試用例中獲得的數據&#xff0c;應該怎么辦&#xff1f; 解決方案一&#xff1a;使用函數返回值 - 我們可以在另一個測試用例中使用return來返回所需的數據&#xff0c;并在其他的測試用例中調用該測試用例&#xff08…

深信服GO面試題及參考答案(上)

Go 和 Java 的特點和區別是什么? Go 和 Java 都是靜態類型、編譯型語言,但在設計理念、語法特性、并發模型等方面存在顯著差異,具體如下: 從語言設計目標來看,Go 由 Google 開發,旨在解決大型系統開發中的復雜性,強調“簡單、高效、并發”,語法簡潔,摒棄了許多傳統面向…