//第一步:組冊組件
? ? 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);