当前位置:网站首页>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
这样把数据流程就分析完了。 结束。
边栏推荐
- Common open source databases under Linux, how many do you know?
- Physical backup issues caused by soft links
- Ant Sword Advanced Module Development
- leetcode - a subtree of another tree
- 【七夕节】浪漫七夕,代码传情。将爱意变成绚烂的立体场景,给她(他)一个惊喜!(送代码)
- Lexicon - the maximum depth of a binary tree
- QStyle platform style
- 汉字转拼音
- 627. 变更性别
- 2022高处安装、维护、拆除考试题模拟考试题库及在线模拟考试
猜你喜欢
Flink 1.15.1 Cluster Construction (StandaloneSession)
dmp(dump)转储文件
Data storage practice based on left-order traversal
The design idea of DMicro, the Go microservice development framework
On governance and innovation, the 2022 OpenAtom Global Open Source Summit OpenAnolis sub-forum came to a successful conclusion
倒计时 2 天|云原生 Meetup 广州站,等你来!
如何在WordPress中添加特定类别的小工具
静态方法获取配置文件数据
[Qixi Festival] Romantic Tanabata, code teaser.Turn love into a gorgeous three-dimensional scene and surprise her (him)!(send code)
.NET Application -- Helloworld (C#)
随机推荐
Never put off till tomorrow what you can put - house lease management system based on the SSM
private封装
2022-08-04 第六小组 瞒春 学习笔记
高项 02 信息系统项目管理基础
Why did they choose to fall in love with AI?
627. Change of gender
(11) Metaclass
PostgreSQL数据库 用navicat 打开表结构的时候报错 cannot update secondarysnapshot during a parallel operation 怎么解决?
QT language file production
The design idea of DMicro, the Go microservice development framework
A small tool to transfer files using QR code - QFileTrans 1.2.0.1
如何在WordPress中添加特定类别的小工具
龙蜥社区第二届理事大会圆满召开!理事换届选举、4 位特约顾问加入
rpc-remote procedure call demo
1873. 计算特殊奖金
[Qixi Festival] Romantic Tanabata, code teaser.Turn love into a gorgeous three-dimensional scene and surprise her (him)!(send code)
Question about #sql shell#, how to solve it?
为什么pca分量没有关联
Object.defineProperty monitors data changes in real time and updates the page
.NET Application -- Helloworld (C#)