8-采用ffmpeg,录制pcm原数据
小白学习音视频(八)采用ffmpeg,录制pcm原数据
关注微信号:cpp手艺人,获取更多文章
先上个流程图
贴上主要的代码:
int _tmain(int argc, char* argv[])
{
av_register_all();
avdevice_register_all();
// 这里获取你的音频设备名称
show_dshow_device();
// 资源容器类
ResourceContainer containter;
// 释放资源函数
std::function<void(void)> release_resource = [&containter] () {
if (nullptr != containter.file_handle) {
fclose(containter.file_handle);
}
if (nullptr != containter.frame) {
av_free(containter.frame);
containter.frame = nullptr;
}
if (nullptr != containter.codec_context) {
avcodec_close(containter.codec_context);
}
avformat_close_input(&(containter.format_context));
avformat_free_context(containter.format_context);
};
// 分配上下文
AVFormatContext *format_context = avformat_alloc_context();
containter.format_context = format_context;
// 需要录制的设备名称,每台机器的可能不一样,需要替换成你自己的设备名称
string device_name = dup_wchar_to_utf8(
L"audio=立体声混音 (2- Realtek High Definition Audio)");
int ret_code = 0;
// 获取输入格式信息
AVInputFormat *input_format = av_find_input_format("dshow");
// 打开设备
if(0 != (ret_code = avformat_open_input(&format_context,
device_name.c_str(),
input_format,
nullptr))) {
cout << av_error(ret_code) << endl;
goto Error;
}
int audioindex = -1;
// 遍历寻找是否有音频流信息
for(int i = 0; i < format_context->nb_streams; i++) {
if(format_context->streams[i]->codec->codec_type ==
AVMEDIA_TYPE_AUDIO) {
audioindex = i;
break;
}
}
if(-1 == audioindex) {
cout << "Didn't find a audio stream." << endl;
goto Error;
}
// 编码上下文
AVCodecContext *codec_context = format_context->streams[audioindex]->codec;
containter.codec_context = codec_context;
// 寻找解码器
AVCodec *codec = avcodec_find_decoder(codec_context->codec_id);
if(nullptr == codec) {
cout << "audio codec not found." << endl;
goto Error;
}
if(0 != (ret_code = avcodec_open2(codec_context, codec, nullptr))) {
cout << av_error(ret_code) << endl;
goto Error;
}
AVFrame *frame = av_frame_alloc();
containter.frame = frame;
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
FILE *fp_pcm = fopen("output.pcm", "wb");
containter.file_handle = fp_pcm;
float total_time = 0;
int got_frame = 0;
for(int i = 0; ; i++) {
//就采集30秒
if (total_time > 30) { break; }
// 读取音频信息失败,直接退出
if(av_read_frame(format_context, packet) < 0) { break; }
if(packet->stream_index == audioindex) {
// 对音频进行解码
if (0 != (ret_code = avcodec_decode_audio4(codec_context,
frame,
&got_frame,
packet))) {
cout << av_error(ret_code) << endl;
goto Error;
}
if (0 == got_frame) { continue; }
int pcm_size =
av_samples_get_buffer_size(nullptr,
codec_context->channels,
frame->nb_samples,
codec_context->sample_fmt,
1);
uint8_t *pcm_buffer = frame->data[0];
float used_time =
frame->nb_samples * 1.0 / codec_context->sample_rate;
total_time += used_time;
// 保存到文件中
fwrite(pcm_buffer, 1, pcm_size, fp_pcm);
}
av_free_packet(packet);
}
release_resource();
return 0;
Error:
release_resource();
return -1;
}
录制的好的pcm文件,使用ffplay播放就可以了。
命令行如下:
播放44.1kHz 双声道 16bit的xxx.pcm的PCM文件为例
ffplay.exe -ar 44100 -channels 2 -f s16le -i xxx.pcm
github地址:https://github.com/MingYueRuYa/FFmpeg-RTMP 在ffmpeg_demo解决方案下面
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 635672377@qq.com
文章标题:8-采用ffmpeg,录制pcm原数据
文章字数:555
本文作者:刘世雄
发布时间:2020-08-13, 11:46:44
最后更新:2020-08-13, 03:46:47
原始链接:http://lsxcpp.com/2020/08/13/8-%E9%87%87%E7%94%A8ffmpeg,%E5%BD%95%E5%88%B6pcm%E5%8E%9F%E6%95%B0%E6%8D%AE/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。