当前位置:网站首页>ffmpeg -sources分析
ffmpeg -sources分析
2022-08-05 03:08:00 【hjjdebug】
ffmpeg -sources分析
----------------------------------------
author:hjjdebug
date: 2022年 08月 03日 星期三 16:42:27 CST
----------------------------------------
先看一下它的输出:
$ ffmpeg -sources
Device name is not provided.
You can pass devicename[,opt1=val1[,opt2=val2...]] as an argument.
Auto-detected sources for alsa:
* default [Playback/recording through the PulseAudio sound server]
surround21 [2.1 Surround output to Front and Subwoofer speakers]
surround40 [4.0 Surround output to Front and Rear speakers]
surround41 [4.1 Surround output to Front, Rear and Subwoofer speakers]
surround50 [5.0 Surround output to Front, Center and Rear speakers]
surround51 [5.1 Surround output to Front, Center, Rear and Subwoofer speakers]
surround71 [7.1 Surround output to Front, Center, Side, Rear and Woofer speakers]
null [Discard all samples (playback) or generate zero samples (capture)]
samplerate [Rate Converter Plugin Using Samplerate Library]
speexrate [Rate Converter Plugin Using Speex Resampler]
jack [JACK Audio Connection Kit]
oss [Open Sound System]
pulse [PulseAudio Sound Server]
upmix [Plugin for channel upmix (4,6,8)]
vdownmix [Plugin for channel downmix (stereo) with a simple spacialization]
sysdefault:CARD=PCH [Default Audio Device]
front:CARD=PCH,DEV=0 [Front speakers]
dmix:CARD=PCH,DEV=0 [Direct sample mixing device]
dmix:CARD=PCH,DEV=2 [Direct sample mixing device]
dsnoop:CARD=PCH,DEV=0 [Direct sample snooping device]
dsnoop:CARD=PCH,DEV=2 [Direct sample snooping device]
hw:CARD=PCH,DEV=0 [Direct hardware device without any conversions]
hw:CARD=PCH,DEV=2 [Direct hardware device without any conversions]
plughw:CARD=PCH,DEV=0 [Hardware device with all software conversions]
plughw:CARD=PCH,DEV=2 [Hardware device with all software conversions]
usbstream:CARD=PCH [USB Stream Output]
usbstream:CARD=NVidia [USB Stream Output]
Auto-detected sources for oss:
Cannot list sources. Not implemented.
Auto-detected sources for sndio:
Cannot list sources. Not implemented.
Auto-detected sources for fbdev:
Could not open framebuffer device '/dev/fb0': Permission denied
Auto-detected sources for lavfi:
Cannot list sources. Not implemented.
Auto-detected sources for video4linux2,v4l2:
Auto-detected sources for x11grab:
Cannot list sources. Not implemented.
下面分析代码:
ffmpeg 分析选项之后,调用了show_sources() 函数,关键代码如下:
fmt = 0;
do {
fmt = av_input_audio_device_next(fmt);
if (fmt) {
print_device_sources(fmt, opts);
}
} while (fmt);
do {
fmt = av_input_video_device_next(fmt);
if (fmt) {
print_device_sources(fmt, opts);
}
} while (fmt);
可见是2个循环.
先看看如何得到fmt. ,由上一个format 可得到下一个format.
int i = 0;
while (prev && (fmt = indev_list[i])) {
i++;
if (prev == fmt) // fmt 与前一个相等了就停下来。
break;
}
do {
fmt = indev_list[i++];
if (!fmt)
break;
category = pc->category;
} while (category != c1 && category != c2); //找到下一个符合要求的,c1,c2是条件
return (AVInputFormat *)fmt;
原来核心是有一个indev_list[]数组, 查找之为:
static const AVInputFormat * const indev_list[] = {
&ff_alsa_demuxer,
&ff_fbdev_demuxer,
&ff_lavfi_demuxer,
&ff_oss_demuxer,
&ff_sndio_demuxer,
&ff_v4l2_demuxer,
&ff_xcbgrab_demuxer,
NULL };
这样我们就知道了,就这么多AVInputFormat. 这是收获1
下面看看每一种AVInputFormat 中具体的项又是怎么得到的?
这要看下面print函数, opts为NULL,fmt 是上面获取的
print_device_sources(fmt, opts);
fmt 的结构比较复杂,相当于一个类。
type = struct AVInputFormat {
const char *name;
const char *long_name;
int flags;
const char *extensions;
const struct AVCodecTag * const *codec_tag;
const AVClass *priv_class;
const char *mime_type;
struct AVInputFormat *next;
int raw_codec_id;
int priv_data_size;
int (*read_probe)(const AVProbeData *);
int (*read_header)(struct AVFormatContext *);
int (*read_packet)(struct AVFormatContext *, AVPacket *);
int (*read_close)(struct AVFormatContext *);
int (*read_seek)(struct AVFormatContext *, int, int64_t, int);
int64_t (*read_timestamp)(struct AVFormatContext *, int, int64_t *, int64_t);
int (*read_play)(struct AVFormatContext *);
int (*read_pause)(struct AVFormatContext *);
int (*read_seek2)(struct AVFormatContext *, int, int64_t, int64_t, int64_t, int);
int (*get_device_list)(struct AVFormatContext *, struct AVDeviceInfoList *);
int (*create_device_capabilities)(struct AVFormatContext *, struct AVDeviceCapabilitiesQuery *);
int (*free_device_capabilities)(struct AVFormatContext *, struct AVDeviceCapabilitiesQuery *);
}
好在别人都写好了,就是上面7种,(当然跟编译选项有关,还可以添加例如decklink等设备)
打印分两部分,一步是获取设备,第二步是打印。
获取设备是关键,信息存入device_list
if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) {
printf("Cannot list sources.\n");
goto fail;
}
打印很简单,调用printf打就是了。
for (i = 0; i < device_list->nb_devices; i++) {
printf("%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
device_list->devices[i]->device_name, device_list->devices[i]->device_description);
}
device_list 需要讲一下,因为它储存了很多信息。数据组织是收获2
AVDeviceInfoList *device_list ;
typedef struct AVDeviceInfoList {
AVDeviceInfo **devices; /**< list of autodetected devices */
int nb_devices; /**< number of autodetected devices */
int default_device; /**< index of default device or -1 if no default */
} AVDeviceInfoList;
2层指针是什么?2层指针是指向表格的指针,这个表格是一个指针表格(一层指针),2层指针解引用是指针。
同样也可以理解3层指针是一个指向2层指针构成的表的指针。解引用就是一个2层指针。当然这里没有使用,类推一下,后面它确实用过3层指针。
因为是一个AVDeviceInfo 列表,所以有一个nb_devices
AVDeviceInfo 是如下定义的,name,description
typedef struct AVDeviceInfo {
char *device_name; /**< device name, format depends on device */
char *device_description; /**< human friendly name */
} AVDeviceInfo;
下面看看如何获取设备列表:
以 ff_alsa_demuxer,为利,抛开它的一些过程,直接来到
return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_CAPTURE); //获取CAPTURE 的列表
该函数把获取到的device 组织到device_list 中,主要流程如下:
if (snd_device_name_hint(-1, "pcm", &hints) < 0) //拿到所有卡信息的hint
return AVERROR_EXTERNAL;
n = hints;
while (*n && !ret) {
name = snd_device_name_get_hint(*n, "NAME");
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if (!io || !strcmp(io, filter)) {
new_device = av_mallocz(sizeof(AVDeviceInfo)); // 分配内存
new_device->device_name = av_strdup(name);
new_device->device_description = av_strdup(descr);
if ((ret = av_dynarray_add_nofree(&device_list->devices, //加入数组
&device_list->nb_devices, new_device)) < 0) {
goto fail;
}
}
free(io);
free(name);
free(descr);
n++;
}
int snd_device_name_hint(int card, const char *iface, void ***hints);
card==-1, 获取所有卡的hint, hints 是3层指针。
char *snd_device_name_get_hint(const void *hint, const char *id);
根据hint和id, 拿到对应的名称。
这两个函数就不是ffmpeg 函数,而是驱动提供的函数了. 最终的数据来自驱动,这是收获3
这样把数据流程就分析完了。 结束。
边栏推荐
- High Item 02 Information System Project Management Fundamentals
- 引领数字医学高地,中山医院探索打造未来医院“新范式”
- 静态方法获取配置文件数据
- AI + Small Nucleic Acid Drugs | Eleven Completes $22 Million Seed Round Financing
- Multithreading (2)
- 【已解决】Unity Coroutinue 协程未有效执行的问题
- sql server installation prompts that the username does not exist
- How to simulate the background API call scene, very detailed!
- 汉字转拼音
- How to solve the error cannot update secondary snapshot during a parallel operation when the PostgreSQL database uses navicat to open the table structure?
猜你喜欢
随机推荐
How OpenGL works
The linear table lookup
【 genius_platform software platform development 】 : seventy-six vs the preprocessor definitions written cow force!!!!!!!!!!(in the other groups conding personnel told so cow force configuration to can
QStyle平台风格
Bubble Sort and Quick Sort
Details such as compiling pretreatment
冒泡排序与快速排序
QStyle platform style
After the large pixel panorama is completed, what are the promotion methods?
STM32 uses stm32cubemx LL library series tutorial
1873. 计算特殊奖金
How to sort multiple fields and multiple values in sql statement
In 2022, you still can't "low code"?Data science can also play with Low-Code!
大像素全景制作完成后,推广方式有哪些?
Open Source License Description LGPL
word分栏小记
QT MV\MVC structure
How to Add Category-Specific Widgets in WordPress
From "useable" to "easy to use", domestic software is self-controllable and continues to advance
PostgreSQL数据库 用navicat 打开表结构的时候报错 cannot update secondarysnapshot during a parallel operation 怎么解决?