日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ffmpeg-从flv文件中提取AAC音频数据保存为文件

發(fā)布時(shí)間:2023/12/1 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ffmpeg-从flv文件中提取AAC音频数据保存为文件 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

AAC ADTS格式協(xié)議:
從flv文件中提取AAC音頻數(shù)據(jù)保存為文件。
如果需要詳細(xì)了解AAC ADTS格式,可以查詢文檔。

原文件:

提取aac文件:

main.c

#include <stdio.h> #include <libavutil/log.h>> #include <libavformat/avio.h> #include <libavformat/avformat.h>#define ADTS_HEADER_LEN 7; const int sampling_frequencies[] = {96000, //0x088200, //0x164000, //0x248000, //0x344100, //0x432000, //0x524000, //0x622050, //0x716000, //0x812000, // 0x911025, // 0xa8000 // 0xb// 0xc d e f是保留的 };int adts_header(char* const p_adts_header, const int data_length,const int profile, const int samplerate, const int channels) {int sampling_frequencies_index = 3; //默認(rèn)使用48000int adtsLen = data_length + 7;//根據(jù)輸入文件的samplerate 獲取 相應(yīng)的在ADTS中設(shè)置的索引int frequencies_size = sizeof(sampling_frequencies) / sizeof(sampling_frequencies[0]);int i = 0;for(i = 0; i < frequencies_size; i++){if(samplerate == sampling_frequencies[i]){sampling_frequencies_index = i;break;}}if(sampling_frequencies_index >= frequencies_size){printf("unsupport samplerate:%d\n", samplerate);return -1;}//同步頭 總是0xFFF(12個(gè)bit),代表著一個(gè)ADTS幀的開始p_adts_header[0] = 0xff;p_adts_header[1] = 0xf0;//MPEG標(biāo)識(shí)符,0標(biāo)識(shí)MPEG-4,1標(biāo)識(shí)MPEG-2(1個(gè)bit)p_adts_header[1] |= (0 << 3);//layer,總是0(2個(gè)bit)p_adts_header[1] |= (0 << 1);//protection_absent ,表示是否誤碼校驗(yàn),1表示 沒有, 0 表示有。(1個(gè)bit)//(注意:ADTS Header的長度在protection_absent = 0 時(shí)占9個(gè)字節(jié), protection_absent = 1時(shí)占7個(gè)字節(jié))p_adts_header[1] |= 1;//profile 使用aac的級(jí)別(質(zhì)量)(2個(gè)bit)//MPEG-4 profile://MAIN = 0//LC = 1//SSR = 2//LTP = 3p_adts_header[2] = (profile)<<6;//采樣率的索引(4個(gè)bit)p_adts_header[2] |= (sampling_frequencies_index & 0x0f) << 2;//private bit: 0 (1個(gè)bit)p_adts_header[2] |= (0 << 1);//聲道(3個(gè)bit)p_adts_header[2] |= (channels & 0x04) >> 2;p_adts_header[3] = (channels & 0x03) << 6;//original_copy = 0 (1個(gè)bit)p_adts_header[3] |= (0 << 5);//home = 0 (1個(gè)bit)p_adts_header[3] |= (0 << 4);//copyright_identification_bit = 0 (1個(gè)bit)p_adts_header[3] |= (0 << 3);//copyright_identification_start = 0 (1個(gè)bit)p_adts_header[3] |= (0 << 2);//frame_length:1個(gè)ADTS幀的長度包括ADTS頭和AAC原始流(13bit)p_adts_header[3] |= ((adtsLen & 0x1800) >> 11);p_adts_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3);p_adts_header[5] = (uint8_t)((adtsLen & 0x7) << 5);//adts_buffer_fullness:0x7FF 說明是碼率可變的碼流p_adts_header[5] |= 0x1f;p_adts_header[6] = 0xfc;//最后還有兩個(gè)bit:number_of_raw_data_blocks_in_frame//表示這個(gè)ADTS幀有幾個(gè)AAC數(shù)據(jù)塊//計(jì)算方法://number_of_raw_data_blocks_in_frame + 1個(gè)AAC原始幀。//所以說number_of_raw_data_blocks_in_frame == 0 表示說ADTS幀中有?個(gè)//AAC數(shù)據(jù)塊。p_adts_header[6] &= 0xfc;//其實(shí)上面p_adts_header[6] = 0xfc的操作這2個(gè)bit已經(jīng)為0了return 0; }int main() {int ret = -1;char errors[1024];char* in_filename = "in_file.flv";char* aac_filename = "test_out.aac";FILE* aac_fd = NULL;int audio_index = -1;int len = 0;AVFormatContext* ifmat_ctc = NULL;AVPacket pkt;//設(shè)置打印級(jí)別av_log_set_level(AV_LOG_DEBUG);aac_fd = fopen(aac_filename, "wb");if(!aac_fd){av_log(NULL, AV_LOG_DEBUG, "Could not open destination file %s\n", aac_filename);return -1;}//打開輸入文件if((ret = avformat_open_input(&ifmat_ctc, in_filename, NULL, NULL)) < 0){av_strerror(ret, errors, 1024);av_log(NULL, AV_LOG_DEBUG, "Could not open source file: %s, %d(%s)\n",in_filename,ret,errors);return -1;}//獲取解碼器信息if((ret = avformat_find_stream_info(ifmat_ctc, NULL)) < 0){av_strerror(ret, errors, 1024);av_log(NULL, AV_LOG_DEBUG, "failed to find stream information: %s, %d(%s)\n",in_filename,ret,errors);return -1;}//dump媒體信息av_dump_format(ifmat_ctc, 0, in_filename, 0);//初始化packetav_init_packet(&pkt);//查找audio對(duì)應(yīng)的stream indexaudio_index = av_find_best_stream(ifmat_ctc, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);if(audio_index < 0){av_log(NULL, AV_LOG_DEBUG, "Could not find %s stream in input file %s\n",av_get_media_type_string(AVMEDIA_TYPE_AUDIO),in_filename);return AVERROR(EINVAL);}//打印aac級(jí)別printf("audio profile:%d , FF_PROFILE_AAC_LOW:%d\n",ifmat_ctc->streams[audio_index]->codecpar->profile,FF_PROFILE_AAC_LOW);if(ifmat_ctc->streams[audio_index]->codecpar->codec_id != AV_CODEC_ID_AAC){printf("the media file no contain AAC stream, it's codec_id is %d\n",ifmat_ctc->streams[audio_index]->codecpar->codec_id);goto END;}//讀取媒體文件,并把a(bǔ)ac數(shù)據(jù)幀寫入本地文件while (av_read_frame(ifmat_ctc, &pkt) >=0 ){if(pkt.stream_index == audio_index){char adts_header_buf[7] = {0};//獲取ADTS幀頭信息adts_header(adts_header_buf, pkt.size,ifmat_ctc->streams[audio_index]->codecpar->profile,ifmat_ctc->streams[audio_index]->codecpar->sample_rate,ifmat_ctc->streams[audio_index]->codecpar->channels);//寫入adts header,ts流不適用,ts流分離出來的packet帶了adts headerfwrite(adts_header_buf, 1, 7, aac_fd);len = fwrite(pkt.data, 1, pkt.size, aac_fd);//寫入adts dataif(len != pkt.size){av_log(NULL, AV_LOG_DEBUG, "warning, length of writed data isn't equal pkt.size(%d, %d)\n",len,pkt.size);}}av_packet_unref(&pkt);}END:if(ifmat_ctc)avformat_close_input(&ifmat_ctc);if(aac_fd)fclose(aac_fd);return 0; }

總結(jié)

以上是生活随笔為你收集整理的ffmpeg-从flv文件中提取AAC音频数据保存为文件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。