Input子系统剖析
Posted 嵌入式开发白菜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Input子系统剖析相关的知识,希望对你有一定的参考价值。
Input子系统是Linux内核中的一个重要组成部分,它负责处理各种输入设备(例如键盘、鼠标等)发送的数据,并将其转换为用户空间可用的格式。本文将介绍Input子系统的基本架构和功能。
Input子系统的基本架构由三个组件构成:驱动程序、输入核心和用户接口。其中,驱动程序负责与硬件设备通信并读取输入数据;输入核心负责将输入数据处理和传递到用户接口;用户接口则提供了访问输入设备数据的API接口。
首先,我们需要了解驱动程序的工作原理。在Linux内核中,每个输入设备都由一个对应的驱动程序进行控制。驱动程序通过注册到Input子系统中,并使用一些特定的API函数来告知内核如何读取输入数据。例如,以下代码演示了如何使用Input子系统API函数注册一个键盘驱动程序:
c复制代码
struct input_dev *dev;
dev = input_allocate_device();
dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SYN);
dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
dev->name = "My Keyboard";
input_register_device(dev);
在上述例子中,input_allocate_device()函数用于分配一个新的输入设备结构体;evbit和keybit数组用于设置设备支持的事件类型和键位;name字段则用于指定设备名称。最后,我们调用input_register_device()函数将输入设备添加到Input子系统中进行管理。
其次,我们需要了解输入核心的工作原理。在驱动程序读取完输入数据之后,它会将数据传递给输入核心进行处理。输入核心首先会进行事件分类,即将不同类别的输入事件(例如按键、鼠标移动等)进行分离。然后,输入核心将这些事件转换为通用格式,并将其存储在内核缓冲区中以供用户空间访问。最后,输入核心通过一些特定的API函数将内核缓冲区中的输入数据传递给用户空间。
最后,我们需要了解用户接口的工作原理。用户接口提供了一组API函数,用于访问内核缓冲区中的输入数据。这些函数包括read()、poll()、select()等,可以根据用户的需求实现阻塞或非阻塞方式的输入数据读取。例如,以下代码演示了如何使用read()函数从输入设备中读取数据:
c复制代码
int fd;
char buf[32];
fd = open("/dev/input/event0", O_RDONLY);
read(fd, buf, sizeof(buf));
在上述例子中,open()函数用于打开一个输入设备文件,并返回一个文件描述符;read()函数则用于从输入设备中读取数据。读取的数据存储在buf缓冲区中,并具有固定的格式。
总之,Input子系统是Linux内核中一个重要的组成部分,负责处理各种输入设备并将其转换为用户空间可用的格式。通过驱动程序、输入核心和用户接口三个组件的协同工作,Input子系统可以实现高效稳定的输入数据读取和处理,并为用户空间提供了一组方便易用的API函数。
FFmpeg init_input函数剖析
函数调用逻辑avformat_open_input
init_input
av_probe_input_buffer2
函数原型
static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options)
函数说明
主要是调用av_probe_input_buffer2函数探测码流格式。AVFormatContext结构体flags变量,在经过avformat_alloc_context创建AVFormatContext结构体对象指针之后,flags值是0x200000(AVFMT_FLAG_AUTO_BSF),含义是等待包数据然后确定码流的文件格式,或者是添加一个字节流的过滤器(Wait for packet data before writing a header, and add bitstream filters as requested by the muxer)
AVFMT_FLAG_DISCARD_CORRUPT 0x0100 ///< Discard frames marked corrupted
AVInputFormat结构体flags变量,在经过av_find_input_format("h264"),返回之后flags的值是0x0100(AVFMT_FLAG_DISCARD_CORRUPT)(Discard frames marked corrupted)
函数代码
static int init_input(AVFormatContext *s, const char *filename,
AVDictionary **options)
{
int ret;
AVProbeData pd = { filename, NULL, 0 };
int score = AVPROBE_SCORE_RETRY;
if (s->pb) {
//当前的flags是0x200000
s->flags |= AVFMT_FLAG_CUSTOM_IO;
//iformat指定h264码流格式之后,不为NULL
if (!s->iformat)
return av_probe_input_buffer2(s->pb, &s->iformat, filename,
s, 0, s->format_probesize);
//s->iformat->flags & AVFMT_NOFILE值为真,但是并没有在日志文件中打印出来Custom AVIOContext makes no sense
else if (s->iformat->flags & AVFMT_NOFILE)
av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
"will be ignored with AVFMT_NOFILE format.\n");
return 0;
}
if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
(!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
return score;
if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)
return ret;
if (s->iformat)
return 0;
return av_probe_input_buffer2(s->pb, &s->iformat, filename,
s, 0, s->format_probesize);
}
以上是关于Input子系统剖析的主要内容,如果未能解决你的问题,请参考以下文章