码迷,mamicode.com
首页 > 其他好文 > 详细

用ffmpeg实现录音

时间:2015-06-19 16:54:19      阅读:1097      评论:0      收藏:0      [点我收藏+]

标签:ffmpeg

1、概述

2、代码

/*
*最简单的录音程序
*缪国凯 MK
*821486004@qq.com
*本程序实现采集麦克风音频数据,压制为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

用ffmpeg实现录音

标签:ffmpeg

原文地址:http://blog.csdn.net/dancing_night/article/details/46561909

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!