• jiangboyue
    了解作者
  • C/C++
    开发工具
  • 2KB
    文件大小
  • zip
    文件格式
  • 0
    收藏次数
  • 1 积分
    下载积分
  • 0
    下载次数
  • 2021-03-02 15:28
    上传日期
windows 采集声卡设备, 并用opus编码,然后保存为文件, 借助ffmpeg, 里面用到的多媒体变量都用到ffmpeg
opus.zip
  • audio_capture_opus.cpp
    7.6KB
  • audio_capture_opus.h
    73B
内容介绍
#include "audio_capture_opus.h" #include "gbk2utf8.h" string GetError4(const int &index){ char buf[256] = { 0 }; av_strerror(index, buf, sizeof(buf)); return string(buf); } int audio_capture_opus() { const char* outPath = "./captureOpus.opus"; /// 查找OPUS音频编码器 const char* codec_name = "libopus"; AVCodec *ACodec = avcodec_find_encoder_by_name(codec_name); if (!ACodec) { cout << "avcodec_find_decoder - faild!" << endl; return -1; } /// 创建音频编码器上下文 AVCodecContext *ACodecContext = avcodec_alloc_context3(ACodec); if (!ACodecContext) { cout << "avcodec_alloc_context3 - faild!" << endl; return -2; } // 设置音频参数 /// 比特率 ACodecContext->bit_rate = 48000; /// 采样率 ACodecContext->sample_rate = 48000; //opus /// 采样格式 假如源音频是AV_SAMPLE_FMT_S16,则用AV_SAMPLE_FMT_S16,我的pcm是AV_SAMPLE_FMT_FLT ACodecContext->sample_fmt = AV_SAMPLE_FMT_S16;//AV_SAMPLE_FMT_S16; /// 通道数 ACodecContext->channels = 2; //必须双通道,不然webrtc不支持 /// 通道类型 ACodecContext->channel_layout = AV_CH_LAYOUT_STEREO; //av_get_default_channel_layout(ACodecContext->channels);// ACodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; /// 打开音频编码器 int result = avcodec_open2(ACodecContext, ACodec, nullptr); if (result != 0) { cout << "avcodec_open2 - faild:" << result << endl; return -3; } /// 打开音频输出封装上下文 AVFormatContext *AFormatContext = nullptr; result = avformat_alloc_output_context2(&AFormatContext, nullptr, nullptr, outPath); if (result < 0) { cout << "avformat_alloc_output_context2 - faild:" << result << endl; return -4; } /// 创建音频输出流 //AVStream *AStream = avformat_new_stream(AFormatContext,ACodec); AVStream *AStream = avformat_new_stream(AFormatContext, nullptr); if (!AStream) { cout << "avformat_new_stream - faild!" << endl; return -5; } /// 音频流媒体附加信息 AStream->codecpar->codec_tag = 0; /// 音频流信息拷贝 result = avcodec_parameters_from_context(AStream->codecpar, ACodecContext); if (result < 0) { cout << "avcodec_parameters_from_context - faild:" << GetError4(result) << endl; return -5; } /// 打印信息 av_dump_format(AFormatContext, 0, outPath, 1); // 打开io,写入头信息 result = avio_open(&AFormatContext->pb, outPath, AVIO_FLAG_WRITE); if (result < 0) { cout << "avio_open - faild:" << GetError4(result) << endl; return -6; } /// 写入头信息,必须编码器初始化好后调用,不然出现意想不到的错误 result = avformat_write_header(AFormatContext, nullptr); if (result == AVSTREAM_INIT_IN_INIT_OUTPUT) { cout << "2 avformat_write_header - faild:" << GetError4(result) << endl; return -7; } /// 创建音频重采样上下文 SwrContext *ASwrContext = nullptr; ASwrContext = swr_alloc_set_opts(NULL, ACodecContext->channel_layout, ACodecContext->sample_fmt, ACodecContext->sample_rate, ACodecContext->channel_layout, AV_SAMPLE_FMT_S16, //注:输入源音频的类型 //48000,//注:输入源音频的采样率 44100,//注:输入源音频的采样率 0, 0); if (!ASwrContext) { cout << "swr_alloc_set_opts - faild:" << endl; return -8; } /// 音频重采样初始化 result = swr_init(ASwrContext); if (result < 0) { cout << "swr_init - faild:" << GetError4(result) << endl; return -9; } AVAudioFifo *fifo = NULL; fifo = av_audio_fifo_alloc(AV_SAMPLE_FMT_S16, 2, 1); AVFormatContext* avFormatCxt = NULL; AVDictionary* options = NULL; char* devicename = const_cast<char*>("audio=Line 1 (Virtual Audio Cable)"); string devicename_utf8_str = GbkToUtf8(devicename); char* devicename_utf8 = const_cast<char*>(devicename_utf8_str.c_str()); cout << devicename_utf8 << endl; avdevice_register_all(); //get format AVInputFormat* inFormat = av_find_input_format("dshow"); av_dict_set(&options, "audio_buffer_size", "100", 0); int ret = avformat_open_input(&avFormatCxt, devicename_utf8, inFormat, &options); av_dump_format(avFormatCxt, 0, "", 0); // Audio: pcm_s16le, 44100 Hz, 2 channels, s16 AVPacket av_packet; int i = 100; /* 是不是一直从设备 读取frame, 直到一定次数,才会 返回一个 packet? // 是不是一直采样 22050次, 然后将数据放入到 avpacket中, 那这样一次,算几帧音频? 那怎么又算一帧呢?*/ void* opus_src_data = av_malloc(960 * 2 * 2); const uint8_t *data2[1]; data2[0] = (uint8_t *)opus_src_data; int k = 0; while (av_read_frame(avFormatCxt, &av_packet) == 0) { printf("size=%d\n", av_packet.size); // 88200 22050 * 2 * 2 if (av_audio_fifo_size(fifo) < 960) { //ret = av_audio_fifo_realloc(fifo, 22050); ret = av_audio_fifo_realloc(fifo, 4410); if (ret < 0) { cout << "av_audio_fifo_realloc err" << endl; } //ret = av_audio_fifo_write(fifo, (void**)dst_data, 22050); ret = av_audio_fifo_write(fifo, (void**)(&(av_packet.data)), 4410); cout << "av_audio_fifo_write ret = " << ret << endl; cout << "fifo size=" << av_audio_fifo_size(fifo) << endl; /*AVFrame* AFrame = av_frame_alloc();*/ while (1) { if (av_audio_fifo_size(fifo) >= 960) { ret = av_audio_fifo_read(fifo, &opus_src_data, 960); /*ret = av_audio_fifo_read(fifo, (void**)AFrame->data, 960);*/ //ret = av_audio_fifo_read(fifo, (void**)data2, 960); if (ret < 0) { cout << GetError4(ret) << endl; } AVFrame* AFrame = av_frame_alloc(); AFrame->format = ACodecContext->sample_fmt;//AV_SAMPLE_FMT_S16; AFrame->channel_layout = ACodecContext->channel_layout;//av_get_default_channel_layout(ACodecContext->channels);// AFrame->nb_samples = ACodecContext->frame_size; // 一帧音频存放的样本数量 cout << "AFrame->nb_samples" << AFrame->nb_samples << endl; AFrame->sample_rate = ACodecContext->sample_rate;//采样率 AFrame->pts = 960 * k;//时间戳,必须写上,不然下面AFrame->extended_data不正确 k++; result = av_frame_get_buffer(AFrame, 0); // 创建音频输出空间 if (result < 0) { cout << "av_frame_get_buffer - faild:" << GetError4(result) << endl; return -9; } /// 转换音频 const uint8_t *data[1]; data[0] = (uint8_t *)opus_src_data; int len = swr_convert(ASwrContext, AFrame->extended_data, AFrame->nb_samples, data, AFrame->nb_samples); if (len <= 0) { break; } /// 音频编码 AVPacket APacket; av_init_packet(&APacket); result = avcodec_send_frame(ACodecContext, AFrame); if (result != 0) { cout << "avcodec_send_frame - faild:" << GetError4(result) << endl; continue; } result = avcodec_receive_packet(ACodecContext, &APacket); if (result != 0) { cout << "avcodec_receive_packet - faild:" << GetError4(result) << endl; continue; } /// 音频封装入opus APacket.stream_index = 0; APacket.dts = 0; cout << "APacket.pts:" << APacket.pts << endl; result = av_interleaved_write_frame(AFormatContext, &APacket); if (result != 0) { cout << "av_interleaved_write_frame - faild:" << GetError4(result) << endl; continue; } } else { break; } } } av_packet_unref(&av_packet); // 不是说 与 av_init_packet 对应操作吗, 这里为什么每次读取packet, 都要unref --i; if (i < 0) { break; } } /// 写入视频索引 av_write_trailer(AFormatContext); /// 关闭视频索引 avio_close(AFormatContext->pb); /// 清理 - 音频封装上下文 avformat_free_context(AFormatContext); /// 关闭编码器 avcodec_close(ACodecContext); /// 清理编码器上下文 avcodec_free_context(&ACodecContext); return 0; }
评论
    相关推荐
    • snapcast:同步多房间音频播放器
      音频被服务器捕获并路由到连接的客户端。 多个播放器可以并行将音频馈送到服务器,并且可以将客户端分组以播放相同的音频流。 使用Snapcast的最通用方法之一是与音乐播放器守护程序( )或结合使用。 它是如何工作...
    • voip-js:VOIP-JS 是一个正在进行的实验,旨在演示如何仅使用 JavaScript 推出您自己的点对点 VOIP 应
      使用带有 getUseMedia API 的 Web 音频上下文,User-1 可以从他们的计算机麦克风捕获音频输入,使用移植到 JavaScript 的音频编码器在客户端对缓冲的数据进行编码,例如: 或 ; 然后可以将压缩包从 Web 浏览器发送...
    • mediadevices-master.zip
      它也可以用于将您的视频/音频编码为各种编解码器选择。 mediadevices消除了与诸如硬件和编解码器之类的交互的复杂性,使您可以专注于构建应用程序,仅通过令人惊讶的简单,轻松和优雅的API进行交互! 安装 go get...
    • 视频会议系统.rar
      一套商用的视频会议程序(cool)。
    • 视频捕获-mpeg4压缩-网络传送源码(VC 6.0).rar
      视频捕获-mpeg4压缩-网络传送源码(VC 6.0).rar
    • VOIP_SRC_ALL.rar
      搞VOIP的一些原代码,包括MGCP,SIP,RTP/TRCP,SRTP(加密RTP)...等源码,参考价值无限!!这可是我所有的收藏阿,我都献给大家了:=)
    • mpeg.zip
      MPEG-2和MP3编解码
    • live.2008.01.04.tar.rar
      网络直播源代码,支持RTSP、RTP,支持的格式包括MPEG-1/2/4,MP3,H264等,功能强大,流媒体开发必须。
    • handvu-beta3.tar.gz
      结合摄像头使用,用于手部位置跟踪,精准度非常高,另可以识别六种手势。其手位跟踪模块可作为手势识别软件的一个组成部分,内含非常详细的说明文档。编译该代码,需要 OpenCV 0.97 或更高版本的支持。在Windows下的编译顺序为cubicles工程、handvu工程,之后根据视频数据来源要求编译其他代码。建议使用 Visual Studio 2003 ,如果需要编译 DirectX 相关模块,则请安装 DirectX SDK 9.0 或更高版本。
    • encore50src.zip
      mpeg4/divx编码程序,多谢qing_lee