//
// Created by chaisy on 2020/11/14.
//
#include <libavutil/log.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <stdio.h>
#include <assert.h>
static void simple_capture_audio()
{
/*
* 输入设备列表
* libavdevice/indev_list.c
* static const AVInputFormat * const indev_list[] = {
* &ff_avfoundation_demuxer,
* &ff_lavfi_demuxer,
* NULL };
*
* 输出设备列表
* libavdevice/outdev_list.c
* static const AVOutputFormat * const outdev_list[] = {
* &ff_audiotoolbox_muxer,
* &ff_opengl_muxer,
* &ff_sdl2_muxer,
* NULL };
*
* 封装器列表
* libavformat/muxer_list.c
* static const AVOutputFormat * const muxer_list[] = {
* &ff_a64_muxer,
* &ff_ac3_muxer,
* &ff_adts_muxer,
* &ff_adx_muxer,
* ...,
* NULL };
*
* 解封装器列表
* libavformat/demuxer_list.c
* static const AVInputFormat * const demuxer_list[] = {
* &ff_aa_demuxer,
* &ff_aac_demuxer,
* &ff_aax_demuxer,
* &ff_ac3_demuxer,
* ...,
* NULL };
*
* avdevice_register_all函数就是将以上数据进行注册
* */
avdevice_register_all();
// 从avdevice_register_all函数注册的输入设备和解封装器列表中进行搜索,并返回有参数short_name指定的数据
// short_name参数的取值可以查阅上述indev_list和demuxer_list数组中每个成员的name属性的值
AVInputFormat *input_format = av_find_input_format("avfoundation");
if (!input_format) {
av_log(NULL, AV_LOG_ERROR, "av_find_input_format failed.");
return;
}
// 分配AVFormatContext
AVFormatContext *format_context = avformat_alloc_context();
if (!format_context) {
av_log(NULL, AV_LOG_ERROR, "avformat_alloc_context failed.");
return;
}
AVDictionary *options = NULL;
// avformat_open_input会执行如下判断
// if (format_context == NULL) format_context = avformat_alloc_context();
// url 参数指定输入数据,可以是本地文件、rtmp流、rtsp流、rtp流等
// fmt 参数是有效值,则直接使用该fmt进行输入数据的解析,否则会自动解析url参数指定的数据,来判断fmt应该是什么数据
// options 参数可以设置采样率、采样大小、分辨率等信息
// 具体内容可通过fmt结构中的priv_class字段中的options参数查看
int ret = avformat_open_input(&format_context, ":0", input_format, NULL);
if (ret) {
av_log(NULL, AV_LOG_ERROR, "avformat_open_input failed, error:%s", av_err2str(ret));
return;
}
AVPacket *pkt = av_packet_alloc();
pkt->data = NULL;
pkt->size = 0;
FILE *output_fd = fopen("out.pcm", "wb+");
assert(output_fd);
while (1) {
ret = av_read_frame(format_context, pkt);
if (ret < 0) {
if (ret == -35) {
continue;
}
break;
}
fwrite(pkt->data, pkt->size, 1, output_fd);
fflush(output_fd);
av_packet_unref(pkt);
}
av_packet_free(&pkt);
avformat_close_input(&format_context);
}
int main(int argc, char *argv[])
{
simple_capture_audio();
return 0;
}