FFmpeg音頻解碼

//第一步:組冊組件

? ? av_register_all();

? ? //第二步:打開封裝格式->打開文件

? ? //參數(shù)一:封裝格式上下文

? ? //作用:保存整個視頻信息(解碼器、編碼器等等...)

? ? //信息:碼率、幀率等...

? ? AVFormatContext* avformat_context = avformat_alloc_context();

? ? //參數(shù)二:視頻路徑

? ? const char *url = [jinFilePath UTF8String];

? ? //參數(shù)三:指定輸入的格式

? ? //參數(shù)四:設(shè)置默認參數(shù)

? ? int avformat_open_input_result = avformat_open_input(&avformat_context, url,NULL, NULL);

? ? if (avformat_open_input_result !=0){

? ? ? ? NSLog("打開文件失敗");

? ? ? ? return;

? ? }

? ? NSLog("打開文件成功");

? ? //第三步:拿到視頻基本信息

? ? //參數(shù)一:封裝格式上下文

? ? //參數(shù)二:指定默認配置

? ? int avformat_find_stream_info_result = avformat_find_stream_info(avformat_context,NULL);

? ? if (avformat_find_stream_info_result <0){

? ? ? ? NSLog("查找失敗");

? ? ? ? return;

? ? }

? ? //第四步:查找音頻解碼器

? ? //第一點:查找音頻流索引位置

? ? int av_stream_index = -1;

? ? for (int i =0; i < avformat_context->nb_streams; ++i) {

? ? ? ? //判斷是否是音頻流

? ? ? ? if (avformat_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){

? ? ? ? ? ? //AVMEDIA_TYPE_AUDIO->表示音頻類型

? ? ? ? ? ? av_stream_index = i;

? ? ? ? ? ? break;

? ? ? ? }

? ? }

? ? //第二點:獲取音頻解碼器上下文

? ? AVCodecContext * avcodec_context = avformat_context->streams[av_stream_index]->codec;

? ? //第三點:獲得音頻解碼器

? ? AVCodec *avcodec = avcodec_find_decoder(avcodec_context->codec_id);

? ? if (avcodec ==NULL){

? ? ? ? NSLog("查找音頻解碼器失敗");

? ? ? ? return;

? ? }

? ? //第五步:打開音頻解碼器

? ? int avcodec_open2_result = avcodec_open2(avcodec_context, avcodec,NULL);

? ? if (avcodec_open2_result !=0){

? ? ? ? NSLog("打開音頻解碼器失敗");

? ? ? ? return;

? ? }

? ? //第六步:讀取音頻壓縮數(shù)據(jù)->循環(huán)讀取

? ? //創(chuàng)建音頻壓縮數(shù)據(jù)幀

? ? //音頻壓縮數(shù)據(jù)->acc格式、mp3格式

? ? AVPacket* avpacket = (AVPacket*)av_malloc(sizeof(AVPacket));

? ? //創(chuàng)建音頻采樣數(shù)據(jù)幀

? ? AVFrame* avframe = av_frame_alloc();

? ? //音頻采樣上下文->開辟了一快內(nèi)存空間->pcm格式等...

? ? //設(shè)置參數(shù)

? ? //參數(shù)一:音頻采樣數(shù)據(jù)上下文

? ? //上下文:保存音頻信息(記錄)->目錄

? ? SwrContext* swr_context = swr_alloc();

? ? //參數(shù)二:out_ch_layout->輸出聲道布局類型(立體聲、環(huán)繞聲、機器人等等...)

? ? //立體聲

? ? int64_t out_ch_layout = AV_CH_LAYOUT_STEREO;

//? ? int out_ch_layout = av_get_default_channel_layout(avcodec_context->channels);

? ? //參數(shù)三:out_sample_fmt->輸出采樣精度->編碼

? ? //直接指定

? ? int out_sample_fmt = AV_SAMPLE_FMT_S16;

? ? //例如:采樣精度8位 = 1字節(jié),采樣精度16位 = 2字節(jié)

? ? //參數(shù)四:out_sample_rate->輸出采樣率(44100HZ)

? ? int out_sample_rate = avcodec_context->sample_rate;

? ? //參數(shù)五:in_ch_layout->輸入聲道布局類型

? ? int64_t in_ch_layout = av_get_default_channel_layout(avcodec_context->channels);

? ? //參數(shù)六:in_sample_fmt->輸入采樣精度

? ? AVSampleFormat in_sample_fmt = avcodec_context->sample_fmt;

? ? //參數(shù)七:in_sample_rate->輸入采樣率

? ? int in_sample_rate = avcodec_context->sample_rate;

? ? //參數(shù)八:log_offset->log日志->從那里開始統(tǒng)計

? ? int log_offset =0;

? ? //參數(shù)九:log_ctx->log上下文

? ? swr_alloc_set_opts(swr_context,

?? ? ? ? ? ? ? ? ? ? ? out_ch_layout,

?? ? ? ? ? ? ? ? ? ? ? out_sample_fmt,

?? ? ? ? ? ? ? ? ? ? ? out_sample_rate,

?? ? ? ? ? ? ? ? ? ? ? in_ch_layout,

?? ? ? ? ? ? ? ? ? ? ? in_sample_fmt,

?? ? ? ? ? ? ? ? ? ? ? in_sample_rate,

?? ? ? ? ? ? ? ? ? ? ? log_offset,NULL);

? ? //初始化音頻采樣數(shù)據(jù)上下文

? ? swr_init(swr_context);

? ? //輸出音頻采樣數(shù)據(jù)

? ? //緩沖區(qū)大小 = 采樣率(44100HZ) * 采樣精度(16位 = 2字節(jié))

? ? int MAX_AUDIO_SIZE =44100 * 2;

? ? uint8_t *out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_SIZE);

? ? //輸出聲道數(shù)量

? ? int out_nb_channels = av_get_channel_layout_nb_channels(out_ch_layout);

? ? int audio_decode_result =0;

? ? //打開文件

? ? const char *coutFilePath = [joutFilePath UTF8String];

? ? FILE* out_file_pcm = fopen(coutFilePath,"wb");

? ? if (out_file_pcm ==NULL){

? ? ? ? NSLog("打開音頻輸出文件失敗");

? ? ? ? return;

? ? }

? ? int current_index =0;

? ? //計算:4分鐘一首歌曲 = 240ms = 4MB

? ? //現(xiàn)在音頻時間:24ms->pcm格式->8.48MB

? ? //如果是一首4分鐘歌曲->pcm格式->85MB

? ? while (av_read_frame(avformat_context, avpacket) >=0){

? ? ? ? //讀取一幀音頻壓縮數(shù)據(jù)成功

? ? ? ? //判定是否是音頻流

? ? ? ? if (avpacket->stream_index == av_stream_index){

? ? ? ? ? ? //第七步:音頻解碼

? ? ? ? ? ? //1、發(fā)送一幀音頻壓縮數(shù)據(jù)包->音頻壓縮數(shù)據(jù)幀

? ? ? ? ? ? avcodec_send_packet(avcodec_context, avpacket);

? ? ? ? ? ? //2、解碼一幀音頻壓縮數(shù)據(jù)包->得到->一幀音頻采樣數(shù)據(jù)->音頻采樣數(shù)據(jù)幀

? ? ? ? ? ? audio_decode_result = avcodec_receive_frame(avcodec_context, avframe);

? ? ? ? ? ? if (audio_decode_result ==0){

? ? ? ? ? ? ? ? //表示音頻壓縮數(shù)據(jù)解碼成功

? ? ? ? ? ? ? ? //3、類型轉(zhuǎn)換(音頻采樣數(shù)據(jù)格式有很多種類型)

? ? ? ? ? ? ? ? //我希望我們的音頻采樣數(shù)據(jù)格式->pcm格式->保證格式統(tǒng)一->輸出PCM格式文件

? ? ? ? ? ? ? ? //swr_convert:表示音頻采樣數(shù)據(jù)類型格式轉(zhuǎn)換器

? ? ? ? ? ? ? ? //參數(shù)一:音頻采樣數(shù)據(jù)上下文

? ? ? ? ? ? ? ? //參數(shù)二:輸出音頻采樣數(shù)據(jù)

? ? ? ? ? ? ? ? //參數(shù)三:輸出音頻采樣數(shù)據(jù)->大小

? ? ? ? ? ? ? ? //參數(shù)四:輸入音頻采樣數(shù)據(jù)

? ? ? ? ? ? ? ? //參數(shù)五:輸入音頻采樣數(shù)據(jù)->大小

? ? ? ? ? ? ? ? swr_convert(swr_context,

? ? ? ? ? ? ? ? ? ? ? ? ? ? &out_buffer,

? ? ? ? ? ? ? ? ? ? ? ? ? ? MAX_AUDIO_SIZE,

? ? ? ? ? ? ? ? ? ? ? ? ? ? (const uint8_t **)avframe->data,

? ? ? ? ? ? ? ? ? ? ? ? ? ? avframe->nb_samples);

? ? ? ? ? ? ? ? //4、獲取緩沖區(qū)實際存儲大小

? ? ? ? ? ? ? ? //參數(shù)一:行大小

? ? ? ? ? ? ? ? //參數(shù)二:輸出聲道數(shù)量

? ? ? ? ? ? ? ? //參數(shù)三:輸入大小

? ? ? ? ? ? ? ? int nb_samples = avframe->nb_samples;

? ? ? ? ? ? ? ? //參數(shù)四:輸出音頻采樣數(shù)據(jù)格式

? ? ? ? ? ? ? ? //參數(shù)五:字節(jié)對齊方式

? ? ? ? ? ? ? ? int out_buffer_size = av_samples_get_buffer_size(NULL,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? out_nb_channels,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nb_samples,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? out_sample_fmt,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1);

? ? ? ? ? ? ? ? //5、寫入文件(你知道要寫多少嗎?)

? ? ? ? ? ? ? ? fwrite(out_buffer,1, out_buffer_size, out_file_pcm);

? ? ? ? ? ? ? ? current_index++;

? ? ? ? ? ? ? ? NSLog("當前音頻解碼第%d幀", current_index);

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? //第八步:釋放內(nèi)存資源,關(guān)閉音頻解碼器

? ? fclose(out_file_pcm);

? ? av_packet_free(&avpacket);

? ? swr_free(&swr_context);

? ? av_free(out_buffer);

? ? av_frame_free(&avframe);

? ? avcodec_close(avcodec_context);

? ? avformat_close_input(&avformat_context);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容