Linux驅動21 --- FFMPEG 音頻 API

?目錄

?一、FFMPEG 音頻 API

1.1 解碼步驟

????????創建核心上下文指針

????????打開輸入流

????????獲取輸入流

????????獲取解碼器

????????初始化解碼器

????????創建輸入流指針

????????創建輸出流指針

????????初始化 SDL

????????配置音頻參數

????????打開音頻設備

????????獲取一幀數據

????????發送給解碼器

????????從解碼器獲取數據

????????開辟數據空間

????????初始化內存????????

????????音頻重采樣配置 --- 相當于視頻的格式轉換

????????由通道數獲取默認的通道布局

????????初始化重采樣核心結構體

????????音頻重采樣

????????播放

????????延時

1.2 參數擴展

????????SDL_AudioSpec

????????AVFrame

二、FFMPEG 錄制聲音的過程

2.1 步驟

????????FFMPEG 注冊所有??

????????FFMPEG 核心上下文申請

????????查找音頻設備

????????注冊音頻設備

????????SDL 初始化

????????配置音頻參數

????????打開音頻設備

????????讀取一幀數據

????????寫入到文件

三、如何在板子上實現


一、FFMPEG 音頻 API

1.1 解碼步驟

????????創建核心上下文指針

????????????????AVFormatContext * avfmtctx? = avformat_alloc_context();

????????打開輸入流

????????????????avformat_open_input(&avfmtctx, argv[1], NULL, NULL);

????????獲取輸入流

????????????????avformat_find_stream_info(avfmtctx, NULL);

????????獲取解碼器

????????????????AVCodecContext * avcodectx = avfmtctx->streams[0]->codec;
? ? ? ? ? ? ? ? AVCodec *avcodec = avcodec_find_decoder(avcodectx->codec_id);

????????初始化解碼器

????????????????avcodec_open2(avcodectx, avcodec, NULL);?

????????創建輸入流指針

????????????????AVPacket * avpkt = av_packet_alloc();

????????創建輸出流指針

????????????????AVFrame * avfrm = av_frame_alloc();?

????????初始化 SDL

????????函數頭文件

????????????????#include <SDL2/SDL.h>

????????函數原型

????????????????int?SDL_Init(Uint32 flags)

????????函數參數

????????????????常用參數

????????????????????????SDL_INIT_TIMER

????????????????????????SDL_INIT_AUDIO

????????????????????????SDL_INIT_VIDEO

????????函數返回值

????????????????成功時返回0,失敗時返回負數錯誤碼; 調用SDL_GetError()可以獲得本次異常信息。

????????配置音頻參數

????????函數原型

????????????????int?SDL_OpenAudioDevice(const char ?*device,int iscapture,const SDL_AudioSpec *desired, SDL_AudioSpec *obtained,int allowed_changes); ?

????????函數參數

????????????????device:音頻設備的名稱,NULL表示使用默認設備

????????????????iscapture:設為0,非0的值在當前SDL2版本還不支持

????????????????desired:期望得到的音頻輸出格式

????????????????obtained:實際的輸出格式

????????????????allowed_changes:該參數用來指定?當期望和實際的不一樣時,能不能夠對某一些輸出參數進行修改。 設為0,則不能修改。設為如下的值,則可對相應的參數修改:

????????????????????????SDL_AUDIO_ALLOW_FREQUENCY_CHANGE

????????????????????????SDL_AUDIO_ALLOW_FORMAT_CHANGE

????????????????????????SDL_AUDIO_ALLOW_CHANNELS_CHANGE

????????????????????????SDL_AUDIO_ALLOW_ANY_CHANGE

????????函數返回值

????????????????0失敗;成功返回有效音頻設備號 >= 2

????????打開音頻設備

????????函數原型

????????????????void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev, int pause_on)

????????函數參數

????????????????dev:SDL_OpenAudioDevice函數返回值

????????????????pause_on:根據介紹,填0即可

????????av_read_frame

????????avcodec_send_packet

????????avcodec_receive_frame

????????獲取一幀數據

????????????????av_read_frame(avfmtctx, avpkt)

????????發送給解碼器

????????????????avcodec_send_packet(avcodectx, avpkt);

????????從解碼器獲取數據

????????????????avcodec_receive_frame(avcodectx, avfrm);

????????開辟數據空間

????????函數原型

????????????????int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align)

????????函數參數

????????????????linesize:計算的lineize,可能為NULL

????????????????nb_channels:聲道數

????????????????SDL_AudioSpec結構體中channels成員變量

????????????????nb_samples:單個通道中的樣本數

????????????????????????采樣頻率(Hz) *當前幀的音頻采樣數/當前幀的音頻數據的采樣率

????????????????sample_fmt:樣本格式

????????????????align:對齊緩沖區大小對齊(0 =默認,1 =無對齊)

????????函數返回值

????????????????需要的緩沖區大小,或失敗時出現負錯誤代碼

????????初始化內存????????

? ? ? ??? ? ? ??調用av_malloc,然后再將內存內容清零

????????函數原型

????????????????void *av_mallocz(size_t size)

????????????????申請數據存放空間

????????音頻重采樣配置 --- 相當于視頻的格式轉換

????????根據輸入和輸出參數,并設置相關選項

????????函數頭文件

????????????????#include "libswresample/swresample.h"

????????函數原型

????????SwrContext *swr_alloc_set_opts(SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx)

????????函數參數

s:可選的現有SwrContext,如果不為NULL,則會使用該現有上下文。out_ch_layout:輸出聲道布局(Channel Layout)通過函數av_get_default_channel_layout獲取根據SDL_AudioSpec的channels獲取out_sample_fmt:輸出采樣格式根據SDL_AudioSpec的format成員選取out_sample_rate:輸出采樣率SDL_AudioSpec的freq成員in_ch_layout:輸入聲道布局通過函數av_get_default_channel_layout獲取輸入流codecpar下的channelsin_sample_fmt:輸入采樣格式輸入流codec下的sample_fmtin_sample_rate:輸入采樣率輸入流codec下的sample_ratelog_offset:日志偏移量,填0即可log_ctx:日志上下文,填NULL即可
????????由通道數獲取默認的通道布局

????????函數原型

????????????????int64_t av_get_default_channel_layout(int nb_channels);? ??

????????初始化重采樣核心結構體

????????函數原型

????????????????int swr_init(struct SwrContext *s);

????????函數參數

????????????????s:swr_alloc_set_opts返回值

????????音頻重采樣

????????????????針對每一幀音頻的處理。把一幀幀的音頻作相應的重采樣

????????函數原型

????????????????int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in, int in_count);

s:音頻重采樣的上下文out:輸出的指針。傳遞的輸出的數組out_count:輸出的樣本數量,不是字節數。單通道的樣本數量。av_samples_get_buffer_size參數nb_samplesin:輸入的數組,AVFrame解碼出來的DATA(成員extended_data)in_count:輸入的單通道的樣本數量AVFrame結構體的nb_samples成員

????????函數返回值

????????????????每個通道輸出的樣本數,失敗為負值

????????播放

????????函數功能

????????????????使用此函數可以在回調設備(即使用了第一套API需要回調函數填充數據的設備)上緩存更多音頻,而不必通過回調函數填充音頻數據。

????????函數原型

????????????????int SDL_QueueAudio(SDL_AudioDeviceID dev, const void* data, Uint32 len)

????????函數參數

????????????????dev:設備ID

????????????????data:需要被填充的數據指針

????????????????len:數據buffer長度,byte為單位

????????????????????????通過函數av_samples_get_buffer_size獲取

????????函數返回值

????????????????0表示成功,非零表示出現異常

????????//av_samples_get_buffer_size

????????延時

????????SDL_Delay

????????SDL_Delay((輸出數據大小) * 1000.0 / (音頻采樣率?* av_get_bytes_per_sample(音頻格式) * 通道數量) - 1);

1.2 參數擴展

????????SDL_AudioSpec

int freq;		freq 每秒鐘發送給音頻設備的sample frame的個數,通常是11025,220502,44100和48000。(sample frame = 樣本精度 * 通道數)//輸入流codec中sample_rate成員
SDL_AudioFormat format;		fromat 每個樣本占用的空間大小及格式,例如 AUDIO_S16SYS,樣本是有符號的16位整數,字節順序(大端還是小端)和系統一樣。更多的格式可參考SDL_AudioFormat。// AUDIO_F32SYS
Uint8 channels; 		channels 通道數,在SDL2.0中支持1(mono),2(stereo),4(quad)和6(5.1)//輸入流codecpar中channels成員
Uint8 silence;			silence 音頻數據中表示靜音的值是多少//填0即可
Uint16 samples;		這是每次讀取的采樣數量,?決定了音頻數據回調的頻率。?例如,?設置為1024時,?表示每次讀取1024個樣本數據,?回調函數被調用一次。?這個值不一定是2的冪指數次方,?最好由AVFrame->nb_samples參數賦值。?// 512Uint16 padding;		對于某些環境需要Uint32 size;			size 緩沖區的大小(字節為單位),當我們想要更多聲音的時候,我們想讓SDL給出來的聲音緩沖區的尺寸。一個比較合適的值在512到8192之間;ffplay使用1024SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */		callback用來音頻設備緩沖區的回調函數
void *userdata;		userdata在回調函數中使用的數據指針

????????AVFrame

typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8uint8_t *data[AV_NUM_DATA_POINTERS]; // 存放媒體數據的指針數組int linesize[AV_NUM_DATA_POINTERS]; // 視頻或音頻幀數據的行寬uint8_t **extended_data; // 音頻或視頻數據的指針數組。int width, height; // 視頻幀的款和高/*** number of audio samples (per channel) described by this frame*/int nb_samples; // 當前幀的音頻采樣數(每個通道)int format; // 視頻幀的像素格式,見enum AVPixelFormat,或音頻的采樣格式,見enum AVSampleFormaint key_frame; // 當前幀是否為關鍵幀,1表示是,0表示不是。AVRational sample_aspect_ratio; // 視頻幀的樣本寬高比int64_t pts; // 以time_base為單位的呈現時間戳(應向用戶顯示幀的時間)。int64_t pkt_dts; // 從AVPacket復制而來的dts時間,當沒有pts時間是,pkt_dts可以替代pts。int coded_picture_number; // 按解碼先后排序的,解碼圖像數int display_picture_number; // 按顯示前后排序的,顯示圖像數。int quality; // 幀質量,從1~FF_LAMBDA_MAX之間取之,1表示最好,FF_LAMBDA_MAX之間取之表示最壞。void *opaque; // user的私有數據。int interlaced_frame; // 圖片的內容是隔行掃描的(交錯幀)。int top_field_first; // 如果內容是隔行掃描的,則首先顯示頂部字段。int sample_rate; // 音頻數據的采樣率uint64_t channel_layout; // 音頻數據的通道布局。/*** AVBuffer引用,當前幀數據。 如果所有的元素為NULL,則此幀不是引用計數。 必須連續填充此數組,* 即如果buf [i]為非NULL,j <i,buf[j]也必須為非NULL。** 每個數據平面最多可以有一個AVBuffer,因此對于視頻,此數組始終包含所有引用。 * 對于具有多于AV_NUM_DATA_POINTERS個通道的平面音頻,可能有多個緩沖區可以容納在此陣列中。 * 然后額外的AVBufferRef指針存儲在extended_buf數組中。*/AVBufferRef *buf[AV_NUM_DATA_POINTERS];AVBufferRef **extended_buf; // AVBufferRef的指針int        nb_extended_buf; // extended_buf的數量enum AVColorSpace colorspace; // YUV顏色空間類型。int64_t best_effort_timestamp; // 算法預測的timestampint64_t pkt_pos; // 記錄上一個AVPacket輸入解碼器的位置。int64_t pkt_duration; // packet的durationAVDictionary *metadata;int channels; // 音頻的通道數。int pkt_size; // 包含壓縮幀的相應數據包的大小。} AVFrame;

二、FFMPEG 錄制聲音的過程

2.1 步驟

????????FFMPEG 注冊所有??

????????頭文件

????????????????#include "libavdevice/avdevice.h"
? ? ? ??函數原型

????????????????void avdevice_register_all(void)

????????FFMPEG 核心上下文申請

????????????????AVFormatContext * avfmtctx? = avformat_alloc_context();

????????查找音頻設備

????????函數原型

????????????????AVInputFormat *av_find_input_format(const char *short_name)

????????函數參數

????????????????直接填alsa即可

????????函數返回值

????????????????就是需要的輸入設備的核心上下文指針

????????注冊音頻設備

????????函數原型

????????????????int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)

????????函數參數

????????????????ps:FFMPEG的核心上下文指針

????????????????url:在此需要使用聲卡的名字

????????????????"plughw:CARD=AudioPCI,DEV=0"

????????????????fmt:av_find_input_format函數返回值

????????????????options:填NULL

????????SDL 初始化

????????????????SDL_Init(SDL_INIT_AUDIO);

????????配置音頻參數

????????函數原型

????????????????int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)

????????????????????????desired:想要的配置

????????????????????????obtained:實際得到的配置,此處填NULL即可

????????打開音頻設備

????????????????void SDL_PauseAudio(int pause_on)

????????讀取一幀數據

????????????????int av_read_frame(AVFormatContext *s, AVPacket *pkt)

????????寫入到文件

????????????????fwrite

三、如何在板子上實現

1、在 buildroot 中勾選 ffmpeg 選項、SDL 選項

2、編譯文件系統 --- 生成新的文件系統

3、燒錄新的文件系統

4、和之前 LVGL 相同 --- 修改 Makefile

????????4.1 CC 換成 buildroot 的交叉編譯工具

????????4.2 把之前該刪除的依賴庫刪除,把需要的庫給加上

5、編譯

????????可能出現的問題

????????buildroot 支持的 ffmpeg 和 SDL 版本和程序中使用的版本不符

6、運行

代碼

dec_audio.c //音頻

#include <stdio.h>
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include <SDL2/SDL.h>int main(int argc, char *argv[])
{if(argc < 2){printf("./play <name>\n");return 0;}//創建核心上下文指針AVFormatContext * avfmtctx  = avformat_alloc_context();//打開輸入流avformat_open_input(&avfmtctx, argv[1], NULL, NULL);//獲取輸入流avformat_find_stream_info(avfmtctx, NULL); //到此會獲取//輸入流獲取之后獲取的是純音頻文件,只有一個流 ,所以還用 avfmt->streams[0]//有的音頻,會帶一個圖片封面 --- 這種音頻會報段錯誤//獲取解碼器AVCodecContext * avcodectx = avfmtctx->streams[0]->codec;AVCodec *avcodec = avcodec_find_decoder(avcodectx->codec_id);//初始化解碼器avcodec_open2(avcodectx, avcodec, NULL); //創建輸入流指針AVPacket * avpkt = av_packet_alloc();   //存放輸入流中一幀圖像//創建輸出流指針AVFrame * avfrm = av_frame_alloc(); //初始化SDLSDL_Init(SDL_INIT_AUDIO);//配置音頻參數SDL_AudioSpec desired, obtained;    //一個期望的,一個獲得的desired.callback = NULL;desired.channels = 2;    //期望的通道數desired.format = AUDIO_S16SYS;  //音頻的格式desired.freq = avcodectx->sample_rate;    //采樣率 --- 需要注意desired.padding = 0;desired.samples = 1152; //采樣數desired.silence = 0;desired.size = 0;       //desired.userdata = NULL;//打開音頻設備SDL_AudioDeviceID aid = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);  //理論上ID會大于0//啟動音頻設備SDLCALL SDL_PauseAudioDevice(aid, 0);enum AVSampleFormat mysfmt;switch(obtained.format){case AUDIO_S16SYS: mysfmt = AV_SAMPLE_FMT_S16; break;case AUDIO_S32SYS: mysfmt = AV_SAMPLE_FMT_S32; break;case AUDIO_F32SYS: mysfmt = AV_SAMPLE_FMT_FLT; break;}int size;uint8_t *data = NULL;while(1){//獲取一幀數據if(av_read_frame(avfmtctx, avpkt) != 0){printf("獲取文件錯誤/到達文件結尾\n");break;}//發送給解碼器avcodec_send_packet(avcodectx, avpkt);//從解碼器獲取數據avcodec_receive_frame(avcodectx, avfrm);    //第一幀和第二幀獲取的大小不一樣 --- 把開辟空間方在里面//開辟數據空間size = av_samples_get_buffer_size(NULL, obtained.channels, avfrm->nb_samples, mysfmt, 0);//初始化內存data = av_mallocz(size);//音頻重采樣配置 --- 相當于視頻的格式轉換struct SwrContext * swrctx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(obtained.channels), mysfmt, obtained.freq, \av_get_default_channel_layout(avcodectx->channels), avcodectx->sample_fmt, avcodectx->sample_rate, 0, NULL);//初始化重采樣核心結構體swr_init(swrctx);//音頻重采樣swr_convert(swrctx, &data, size, avfrm->extended_data, avfrm->nb_samples);//播放SDL_QueueAudio(aid, data, size);//延時//SDL_Delay((輸出數據大小) * 1000.0 / (音頻采樣率 * av_get_bytes_per_sample(音頻格式) * 通道數量) - 1);SDL_Delay((size) * 1000.0 / (obtained.freq * av_get_bytes_per_sample(mysfmt) * obtained.channels) - 1);    //網上有兩種說法,1.當前的音頻播放需要時間 2.音頻幀不夠,通過延時,補全av_free(data);}
}

get_audio.c //錄音

#include <stdio.h>
#include "libavformat/avformat.h"
#include <SDL2/SDL.h>
#include <pthread.h>
#include <unistd.h>
#include "libavdevice/avdevice.h"int end_flag = 0;void *pthread_count_func(void *arg)
{int num = 0;while(num--){sleep(1);printf("錄音剩余 %d 秒\n", num);}end_flag = 1;
}int main(void)
{//FFMPEG注冊所有 --- 必須寫avdevice_register_all();//FFMPEG核心上下文申請AVFormatContext * avfmtctx  = avformat_alloc_context();//查找音頻設備AVInputFormat * avifmt = av_find_input_format("alsa");//注冊音頻設備avformat_open_input(&avfmtctx, "hw:CARD=AudioPCI,DEV=0", avifmt, NULL);//SDL初始化SDL_Init(SDL_INIT_AUDIO);//配置音頻參數 --- 再此配置為期望的,得到的填NULL即可SDL_AudioSpec desired;    //一個期望的,一個獲得的desired.callback = NULL;desired.channels = 2;    //期望的通道數desired.format = AUDIO_S16SYS;  //音頻的格式desired.freq = 48000;    //采樣率 --- 過低聲音會很奇怪desired.padding = 0;desired.samples = 1152; //采樣數desired.silence = 0;desired.size = 0;       //desired.userdata = NULL;SDL_OpenAudio(&desired, NULL);//打開音頻設備SDL_PauseAudio(0);AVPacket * avpkt = av_packet_alloc();   //存放輸入流中一幀數據FILE *file = fopen("./9203.pcm", "w");pthread_t pd = 0;pthread_create(&pd, NULL, pthread_count_func, NULL);while(1){if(end_flag){break;}//讀取一幀數據av_read_frame(avfmtctx, avpkt);//寫入到文件fwrite(avpkt->data, 1, avpkt->size, file);}fclose(file);return 0;
}

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

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

相關文章

《計算機“十萬個為什么”》之 [特殊字符] 序列化與反序列化:數據打包的奇妙之旅 ??

《計算機“十萬個為什么”》之 &#x1f4e6; 序列化與反序列化&#xff1a;數據打包的奇妙之旅 ??歡迎來到計算機“十萬個為什么”系列&#xff01; 本文將以「序列化與反序列化」為主題&#xff0c;深入探討計算機世界中數據的打包與解包過程。 讓我們一起解開數據的神秘面…

機器學習與深度學習評價指標

機器學習與深度學習評價指標完全指南 ?? 為什么需要評價指標? 想象你是一位醫生,需要判斷一個診斷模型的好壞。如果模型說"這個病人有癌癥",你需要知道: 這個判斷有多準確? 會不會漏掉真正的癌癥患者? 會不會誤診健康的人? 評價指標就像是給AI模型打分的&…

Hugging Face-環境配置

打開anaconda promptconda activate pytorchpip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers datasets tokenizerspycharm找到pytorch下的python.exe#將模型下載到本地調用 from transformers import AutoModelForCausalLM,AutoTokenizer#將模型和分詞工…

cnn中池化層作用

一、池化層概述 在卷積神經網絡中&#xff0c;池化層是核心組件之一&#xff0c;主要作用是逐步降低特征圖的空間尺寸即寬和高&#xff0c;從而減少計算量、控制過擬合并增強模型的魯棒性。 核心作用 降維與減少計算量 壓縮特征圖的尺寸&#xff0c;顯著減少后續層的參數數量和…

寫一個音樂爬蟲

今天我們寫一個網易云音樂的爬蟲&#xff0c;爬取網易云音樂熱歌榜音樂鏈接并下載&#xff0c;這里用到了之前引用的BeautifulSoup和requests。 BeautifulSoup是一個Python庫&#xff0c;用于從HTML和XML文件中提取數據。它提供了一種簡單的方式來遍歷文檔樹和搜索文檔樹中的元…

戰斗公式和傷害走配置文件

故事背景&#xff0c;上次屬性計算用的配置&#xff0c;這次傷害計算也走配置&#xff0c;下面是測試代碼和測試數據local formulas {[100001]{id 100001,name "基礎傷害",formula "function (self,tag,ishit,iscritial,counterratio)\n if ishit1 then\n …

線性代數 上

文章目錄線性代數知識整理一、求行列式1、 套公式2、利用性質&#xff0c;化為可套公式3、抽象行列式4、抽象向量二、代數余子式的線性組合三、求AnA^nAn四、證明A可逆五、求A的逆1、定義法2、初等變換3、公式六、求秩七、線性表示的判定八、線性無關九、求極大線性無關組十、等…

紅帽AI推理服務器三大特點

生成式人工智能&#xff08;Gen AI&#xff09;的迅猛發展&#xff0c;對大型語言模型&#xff08;LLM&#xff09;的部署提出了更高的性能、靈活性和效率要求。無論部署在何種環境中&#xff0c;紅帽AI推理服務器都為用戶提供經過強化并獲得官方支持的vLLM發行版&#xff0c;配…

開始記錄一步步學習pcl

安裝參考&#xff0c;大神寫的非常詳細&#xff0c;一步到位 https://blog.csdn.net/qq_36812406/article/details/144307648?ops_request_misc%257B%2522request%255Fid%2522%253A%25220e215e6ac266b90ded12ed6b2eab1257%2522%252C%2522scm%2522%253A%252220140713.13010233…

Linux系統Centos7 安裝mysql5.7教程 和mysql的簡單指令

目錄 一. 安裝 MySQL 官方 Yum 倉庫 二. 安裝 MySQL 5.7 1.查看可用的mysql版本倉庫 2.啟用MySql5.7倉庫 3.禁用更高版本的倉庫&#xff08;可選&#xff09; 4.導入 MySQL GPG 公鑰 5.安裝MySql5.7 三. 啟動 MySQL 服務 1.啟動 MySQL 服務 2. 設置開機自啟 3.查看服…

嵌入式——C語言:指針③

一、函數指針和指針函數&#xff08;一&#xff09;指針函數&#xff1a;是函數&#xff0c;函數的返回值是指針1.不能返回局部變量的值2.指針函數返回的地址可以作為下一個函數調用的參數&#xff08;二&#xff09;函數指針&#xff1a;是指針&#xff0c;指針指向一個函數in…

OpenCV(05)直方圖均衡化,模板匹配,霍夫變換,圖像亮度變換,形態學變換

【OpenCV&#xff08;01&#xff09;】基本圖像操作、繪制&#xff0c;讀取視頻 【OpenCV&#xff08;02&#xff09;】圖像顏色處理&#xff0c;灰度化&#xff0c;二值化&#xff0c;仿射變換 【OpenCV&#xff08;03&#xff09;】插值方法&#xff0c;邊緣填充&#xff0…

常見的未授權訪問漏洞靶場-練習教程

一.Redis未授權訪問漏洞1.首先需要準備一個vps和vulhub靶場&#xff0c;然后進入目錄。命令:進入靶場目錄&#xff1a;cd /etc/vulhub-master/redis/4-unacc 啟動靶場&#xff1a;docker-compose up -d2.然后啟動我們kali,下載redis服務然后連接redis&#xff0c;并執行命令。…

EAP(基于事件的異步編程模式)

&#x1f4dc; 1. 核心思想 &#x1f4cc; 事件驅動解耦 異步操作通過事件通知結果&#xff0c;調用者無需阻塞線程&#xff0c;通過事件處理器響應操作完成、錯誤或取消。 &#x1f4cc; 線程池與UI線程協同 耗時操作在后臺線程池執行&#xff0c;完成后通過 SynchronizationC…

【三橋君】如何解決后端Agent和前端UI之間的交互問題?——解析AG-UI協議的神奇作用

?你好&#xff0c;我是 ?三橋君? &#x1f4cc;本文介紹&#x1f4cc; >> 一、引言 在智能體&#xff08;Agent&#xff09;領域&#xff0c;MCP、A2A、ANP等協議已經規范了Agent與工具、Agent與Agent之間的通信&#xff0c;但Agent與用戶之間的交互一直缺乏標準化。…

面試官:詳細說說Kafka rebalance 的策略以及具體過程

hello啊&#xff0c;各位觀眾姥爺們&#xff01;&#xff01;&#xff01;本baby今天又來報道了&#xff01;哈哈哈哈哈嗝&#x1f436; 程序員各種工具大全 Kafka 的 Rebalance&#xff08;再平衡&#xff09; 是消費者組&#xff08;Consumer Group&#xff09;在消費者數量…

C++入門自學Day2-- c++類與對象(初識)

一、面向對象和面向過程1、什么是面向過程&#xff08;Process-Oriented Programming, POP&#xff09;&#x1f4cc; 定義面向過程強調的是 過程&#xff08;過程函數&#xff09;&#xff0c;即&#xff1a;按照步驟&#xff08;流程&#xff09;組織代碼。程序結構 數據結構…

DAO組織智能合約開發:從理論到實踐

目錄 DAO組織智能合約開發:從理論到實踐 1. DAO概述:去中心化自治組織 2. DAO核心組件設計 2.1 架構設計 2.2 關鍵智能合約 3. 治理代幣實現 3.1 ERC20擴展合約 4. 提案管理系統實現 4.1 提案狀態機 4.2 提案合約實現 5. DAO核心合約實現 5.1 DAO合約架構 5.2 提案類型擴展 6…

Ubuntu系統完整配置教程

Ubuntu系統完整配置教程 目錄 配置鏡像源安裝網絡服務虛擬機中安裝CUDAPython開發環境配置Java開發環境配置 1. 配置鏡像源 1.1 備份原始源文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup1.2 編輯源文件 sudo nano /etc/apt/sources.list1.3 各大鏡像源…

【mysql慢查詢】

mysql慢查詢慢查詢慢查詢日志配置慢查詢 慢查詢是指執行時間超過指定閾值的SQL語句。在MySQL中&#xff0c;默認情況下執行時間超過10秒的查詢會被認為是慢查詢&#xff0c;但這個閾值可以根據需要進行調整。 慢查詢日志配置 -- 查看當前慢查詢配置 SHOW VARIABLES LIKE slo…