NO IMAGE

ffmpeg錄音

Qt 5.9
ffmpeg 4.0.1
audacity https://www.audacityteam.org/
cooledit https://download.csdn.net/download/wyy626562203/10565903

#include <stdio.h>
#include <QAudioDeviceInfo>
#include <qDebug>
#include <QTextCodec>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}
//Show Dshow Device
void show_dshow_device(){
AVFormatContext *pFormatCtx = avformat_alloc_context();
AVDictionary* options = NULL;
av_dict_set(&options,"list_devices","true",0);
AVInputFormat *iformat = av_find_input_format("dshow");
printf("========Device Info=============\n");
avformat_open_input(&pFormatCtx,"video=dummy",iformat,&options);
printf("================================\n");
}
int main(int argc, char* argv[])
{
AVFormatContext *pFormatCtx;
int             i, audioindex;
AVCodecContext  *aCodecCtx;
AVCodec         *aCodec = NULL;
AVFrame *aFrame;
// 註冊解碼器
av_register_all();
//註冊裝置
avdevice_register_all();//Register Device
//顯示音視訊裝置
show_dshow_device();
pFormatCtx = avformat_alloc_context();
//使用Qt介面獲取輸入裝置名稱
QString psDevName = "audio="   QAudioDeviceInfo::availableDevices(QAudio::AudioInput).at(0).deviceName();
AVInputFormat *ifmt = av_find_input_format("dshow");
//開啟流裝置
if(avformat_open_input(&pFormatCtx,psDevName.toStdString().c_str(),ifmt,NULL)!=0)
{
fprintf(stderr,"Couldn't open input stream.\n");
return -1;
}
audioindex = -1;
aCodecCtx = NULL;
//尋找音訊流
for(i=0; i<pFormatCtx->nb_streams; i  )
{
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
{
audioindex=i;
break;
}
}
//沒有找到視訊流
if(audioindex==-1)
{
printf("Didn't find a video stream.\n");
return -1;
}
//獲取解碼器上下文
aCodecCtx = pFormatCtx->streams[audioindex]->codec;
//獲取音訊解碼器
aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
if(aCodec == NULL)
{
printf("audio Codec not found.\n");
return -1;
}
//開啟音訊解碼器
if(avcodec_open2(aCodecCtx, aCodec,NULL)<0)
{
printf("Could not open audio codec.\n");
return -1;
}
aFrame=av_frame_alloc();
int ret, got_frame;
AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));
//開啟輸出檔案
FILE *fp_pcm=fopen("output.pcm","wb");
//輸出音訊資訊
qDebug()<< "sample format:  " << aCodecCtx->sample_fmt << "(0-8bit 1-16bit)";
qDebug()<< "sample bit:     " << aCodecCtx->bit_rate;
qDebug()<< "sample rate:    " << aCodecCtx->sample_rate;
qDebug()<< "sample channels:" << aCodecCtx->channels;
float Time = 0;
for(int i=0;;i  )
{
if (Time > 30) break; //就採集30秒
//讀取音訊資料
if(av_read_frame(pFormatCtx, packet) < 0)
{
break;
}
//判斷是否是音訊流
if(packet->stream_index==audioindex)
{
#if 0 //廢棄的方法
ret = avcodec_decode_audio4(aCodecCtx, aFrame, &got_frame, packet);
if(ret < 0)
{
fprintf(stderr,"Audio Error.\n");
return -1;
}
if (got_frame)
{
int pcmSize = av_samples_get_buffer_size(NULL,aCodecCtx->channels, aFrame->nb_samples,aCodecCtx->sample_fmt, 1);
uint8_t * pcmBuffer = aFrame->data[0];
float useTime = aFrame->nb_samples * 1.0 / aCodecCtx->sample_rate;
Time  = useTime;
qDebug()<<i<<Time<<useTime;
fwrite(pcmBuffer,1,pcmSize,fp_pcm); //寫入檔案
}
#else   //新方法
ret = avcodec_send_packet(aCodecCtx, packet);
if (ret != 0)
{
fprintf(stderr,"Audio Error.\n");
return -1;
}
while( avcodec_receive_frame(aCodecCtx, aFrame) == 0)
{
int pcmSize = av_samples_get_buffer_size(NULL,aCodecCtx->channels, aFrame->nb_samples,aCodecCtx->sample_fmt, 1);
uint8_t * pcmBuffer = aFrame->data[0];
float useTime = aFrame->nb_samples * 1.0 / aCodecCtx->sample_rate;
Time  = useTime;
qDebug()<<i<<Time<<useTime;
fwrite(pcmBuffer,1,pcmSize,fp_pcm); //寫入檔案
}
#endif
}
av_free_packet(packet);
}
fclose(fp_pcm);
if (aFrame != NULL)
{
av_free(aFrame);
aFrame = NULL;
}
if (aCodecCtx != NULL)
avcodec_close(aCodecCtx);
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
return 0;
}