1、概述
2、代码
/* *最简单的录音程序 *缪国凯 MK *[email protected] *本程序实现采集麦克风音频数据,压制为aac *2015-6-19 */ #include "stdafx.h" #include <windows.h> #include <DShow.h> #include <comutil.h> #pragma comment(lib,"Strmiids") #pragma comment(lib,"comsuppw.lib") #include <conio.h> #pragma comment(lib,"winmm") #define SAFE_RELEASE(x) {if(x != NULL) x->Release();x=NULL;} #ifdef __cplusplus extern "C" { #endif #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libavdevice/avdevice.h" #include "libavutil/audio_fifo.h" #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avformat.lib") #pragma comment(lib, "avutil.lib") #pragma comment(lib, "avdevice.lib") #pragma comment(lib, "avfilter.lib") //#pragma comment(lib, "postproc.lib") //#pragma comment(lib, "swresample.lib") //#pragma comment(lib, "swscale.lib") #ifdef __cplusplus }; #endif _bstr_t strDeviceName; static char *dup_wchar_to_utf8(wchar_t *w); int _tmain(int argc, _TCHAR* argv[]) { AVFormatContext * pFmtCtx = NULL, *ofmt_ctx_a = NULL; AVInputFormat * pAudioInputFmt = NULL; AVOutputFormat * pAudioOutputFmt = NULL; AVStream * pAudioStream = NULL; AVCodecContext * pOutputCodecCtx = NULL; AVCodecContext * pInputCodecCtx = NULL; AVCodec * pCodec = NULL; AVFrame * pAudioFrame = NULL; uint8_t * pFrameBuffer = NULL; int iAudioIndex = -1; //注册FFMPEG库 av_register_all(); avdevice_register_all(); //查找输入方式 pAudioInputFmt =av_find_input_format("dshow"); assert(pAudioInputFmt != NULL); //以Direct Show的方式打开设备,并将 输入方式 关联到格式上下文 char * psDevName = dup_wchar_to_utf8(L"audio=麦克风 (Realtek High Definition Au"); assert(avformat_open_input(&pFmtCtx,psDevName,pAudioInputFmt,NULL) == 0); // avformat_find_stream_info(pFmtCtx,NULL); if(avformat_find_stream_info(pFmtCtx,NULL)<0) return -1; for(int i=0; i<pFmtCtx->nb_streams; i++) { if(pFmtCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO) { iAudioIndex=i; AVCodec *tmpCodec = avcodec_find_decoder(pFmtCtx->streams[i]->codec->codec_id); if(0 > avcodec_open2(pFmtCtx->streams[i]->codec, tmpCodec, NULL)) { printf("can not find or open decoder!\n"); } break; } } av_dump_format(pFmtCtx, 0, NULL, 0); avformat_alloc_output_context2(&ofmt_ctx_a, NULL, NULL, "abc.aac"); pAudioStream = avformat_new_stream(ofmt_ctx_a, NULL); pAudioStream->codec->codec = avcodec_find_encoder(ofmt_ctx_a->oformat->audio_codec); pOutputCodecCtx = pAudioStream->codec; pOutputCodecCtx->sample_rate = pFmtCtx->streams[0]->codec->sample_rate; pOutputCodecCtx->channel_layout = ofmt_ctx_a->streams[0]->codec->channel_layout; pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pAudioStream->codec->channel_layout); if(pOutputCodecCtx->channel_layout == 0) { pOutputCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO; pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pOutputCodecCtx->channel_layout); } pOutputCodecCtx->sample_fmt = pAudioStream->codec->codec->sample_fmts[0]; AVRational time_base={1, pAudioStream->codec->sample_rate}; ofmt_ctx_a->streams[0]->time_base = time_base; //audioCodecCtx->time_base = time_base; pOutputCodecCtx->codec_tag = 0; if (ofmt_ctx_a->oformat->flags & AVFMT_GLOBALHEADER) pOutputCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; if (avcodec_open2(pOutputCodecCtx, pOutputCodecCtx->codec, 0) < 0) { //编码器打开失败,退出程序 exit(0); } if (!(ofmt_ctx_a->oformat->flags & AVFMT_NOFILE)) { if (avio_open(&ofmt_ctx_a->pb, "abc.aac", AVIO_FLAG_WRITE) < 0) { printf( "Could not open output file abc.aac"); } } if (avformat_write_header(ofmt_ctx_a, NULL) < 0) { printf( "Error occurred when opening audio output file\n"); } AVPacket pkt, pkt_out; // FILE * fp = fopen("C:\\Users\\jk\\Desktop\\abc","wb+"); // assert(fp != NULL); AVFrame *frame; AVAudioFifo *fifo = NULL; fifo = av_audio_fifo_alloc(pOutputCodecCtx->sample_fmt,pOutputCodecCtx->channels,1); int frameIndex = 0; while (av_read_frame(pFmtCtx,&pkt) == 0 && _kbhit()==0) { int gotframe = -1; frame = av_frame_alloc(); if (avcodec_decode_audio4(pFmtCtx->streams[iAudioIndex]->codec, frame, &gotframe, &pkt) < 0) { av_frame_free(&frame); printf("can not decoder a frame"); break; } av_free_packet(&pkt); if (!gotframe) { continue;//没有获取到数据,继续下一次 } //test write pcm if(0) { FILE *p = NULL; p = fopen("test.pcm", "a+b"); int tempLenght = 2 * frame->nb_samples;//由于实验中知道这是16位深,所以才这么写 uint8_t *tmpPtr = frame->data[0]; if (NULL != p) { while(tempLenght > 0) { size_t temp = fwrite(tmpPtr, 1, tempLenght, p); tmpPtr+= temp; tempLenght = tempLenght - temp; } fclose(p); } } if (pFmtCtx->streams[iAudioIndex]->codec->sample_fmt != pOutputCodecCtx->sample_fmt || pFmtCtx->streams[iAudioIndex]->codec->channels != pOutputCodecCtx->channels || pFmtCtx->streams[iAudioIndex]->codec->sample_rate != pOutputCodecCtx->sample_rate) { //如果输入和输出的音频格式不一样 需要重采样,这里是一样的就没做 } av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame->nb_samples); av_audio_fifo_write(fifo, (void **)frame->data, frame->nb_samples); //循环读取数据,直到buf里数据采样数不够 while(av_audio_fifo_size(fifo) >= (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : 1024)) { av_frame_free(&frame); frame = av_frame_alloc(); frame->nb_samples = pOutputCodecCtx->frame_size>0 ? pOutputCodecCtx->frame_size: 1024; frame->channel_layout = pOutputCodecCtx->channel_layout; frame->format = pOutputCodecCtx->sample_fmt; frame->sample_rate = pOutputCodecCtx->sample_rate; av_frame_get_buffer(frame, 0); av_audio_fifo_read(fifo, (void **)frame->data, (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : 1024)); av_init_packet(&pkt_out); //frame->pts = pFrame->pts; int got_picture = -1; pkt_out.data = NULL; pkt_out.size = 0; if (avcodec_encode_audio2(pOutputCodecCtx, &pkt_out, frame, &got_picture) < 0) { printf("can not decoder a frame"); } av_frame_free(&frame); if (got_picture) { pkt_out.pts = frameIndex * pOutputCodecCtx->frame_size; pkt_out.dts = frameIndex * pOutputCodecCtx->frame_size; pkt_out.duration = pOutputCodecCtx->frame_size; av_write_frame(ofmt_ctx_a, &pkt_out); frameIndex++; } } } av_write_trailer(ofmt_ctx_a); avio_close(ofmt_ctx_a->pb); avformat_free_context(ofmt_ctx_a); //解初始化 if (pFmtCtx != NULL) { avformat_free_context(pFmtCtx); pFmtCtx = NULL; } return 0; } static char *dup_wchar_to_utf8(wchar_t *w) { char *s = NULL; int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0); s = (char *) av_malloc(l); if (s) WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0); return s; }
3、工程下载地址
http://download.csdn.net/detail/dancing_night/8822669
时间: 2024-09-30 11:52:43