当前位置:网站首页>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
这样把数据流程就分析完了。 结束。
边栏推荐
- QT:神奇QVarient
- Use SuperMap iDesktopX data migration tool to migrate map documents and symbols
- Linux下常见的开源数据库,你知道几个?
- 【Daily Training】1403. Minimum Subsequence in Non-Increasing Order
- How to sort multiple fields and multiple values in sql statement
- Cloud Native (32) | Introduction to Platform Storage System in Kubernetes
- 通过模拟Vite一起深入其工作原理
- Why is the pca component not associated
- Question about #sql shell#, how to solve it?
- Use SuperMap iDesktopX data migration tool to migrate ArcGIS data
猜你喜欢

word column notes

Multithreading (2)

Flink 1.15.1 Cluster Construction (StandaloneSession)

Talking about data security governance and privacy computing

人人都在说的数据中台,你需要关注的核心特点是什么?

腾讯云【Hiflow】新时代自动化工具

Cloud Native (32) | Introduction to Platform Storage System in Kubernetes

使用二维码传输文件的小工具 - QFileTrans 1.2.0.1

QT MV\MVC structure

大像素全景制作完成后,推广方式有哪些?
随机推荐
使用二维码传输文件的小工具 - QFileTrans 1.2.0.1
undo问题
告白数字化转型时代,时速云镌刻价值新起点
Dynamic management of massive service instances
1667. 修复表中的名字
思考(八十八):使用 protobuf 自定义选项,做数据多版本管理
Lexicon - the maximum depth of a binary tree
HDU 1114: Piggy-Bank ← The Complete Knapsack Problem
Open Source License Description LGPL
In 2022, you still can't "low code"?Data science can also play with Low-Code!
Is your data safe in this hyperconnected world?
开源协议说明LGPL
Tencent Cloud [Hiflow] New Era Automation Tool
Programmer's Tanabata Romantic Moment
冒泡排序与快速排序
Intersection of Boolean Operations in SuperMap iDesktop.Net - Repairing Complex Models with Topological Errors
QT MV\MVC structure
Note that Weifang generally needs to pay attention to issuing invoices
private package
Question about #sql shell#, how to solve it?