FFMPEG中INPUT和DEMUX分家

本文介绍FFMPEG架构中INPUT模块与DEMUX模块的分离设计,旨在简化播放器维护工作。通过新增URLProtocol类型mem_protocol,实现从不同来源获取数据并统一处理。

转载时请注明出处和作者
文章出处:http://www.nanbandao.com/bbs/
作者:Ella
为了播放器容易维护,应老大要求,INPUT模块和DEMUX模块必须分家。
INPUT模块是指通过各种方式(如读本地文件,http,udp,rtsp等等)将数据写到一段内存中,DEMUX模块只负责从相应的内存中取数据,也就是INPUT在一个线程,DEMUX在另外的线程里。
FFMPEG的架构是DEMUX需要数据时,先访问Buffer2,Buffer2如果有数据,则直接使用,如果没有,则调用INPUT模块的api,读 数据并将数据写入到Buffer1,然后将Buffer1的数据memcpy到Buffer2。Buffer1的初始化在 av_open_input_file函数的url_fopen的url_fdopen函数处理的,普通大小是1M;而Buffer2的大小是根据 DEMUX要求临时生成的buffer。向Buffer1写数据依赖于URLProtocol结构体,先看看该结构体的定义。
typedef struct URLProtocol
{
    const char *name;
    int (*url_open)(URLContext *h, const char *filename, int flags);
    int (*url_read)(URLContext *h, unsigned char *buf, int size);
    int (*url_write)(URLContext *h, unsigned char *buf, int size);
    int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
    int (*url_close)(URLContext *h);
    struct URLProtocol *next;
    int (*url_read_pause)(URLContext *h, int pause);
    int64_t (*url_read_seek)(URLContext *h, int stream_index,
                             int64_t timestamp, int flags);
} URLProtocol;
函数指针url_open是根据当前name进行open的,如果的本地文件,则直接open该文件,如果是http,则需要进行socket通信,并判 断socket是否成功建立;url_read,将数据读入buf所指向的内存中,url_write将数据写入buf,url_seek,seek到指 定的地方;url_close:realease open时相关的资源。
FFMPEG数据获取和DEMUX数据获取关系.JPG


为了INPUT从FFMPEG分开,且符合FFMPEG架构,则构建了如下模型。
INPUT和DEMUX模块的关系.JPG


  Buffer1和Buffer2的关系不变,变的是向Buffer1写数据模块,因此增加了一个新的URLProtocol类型,
URLProtocol mem_protocol =
{
    "mem",
    mem_data_open,
    mem_data_read,
    mem_data_write,
    mem_data_seek,
    mem_data_close,
};
而且需要在ffmpeg/libavformat/allformat.c 中注册REGISTER_PROTOCOL(MEM,mem);依次实现mem_data_open、mem_data_read、 mem_data_write、mem_data_seek、mem_data_close。
这样FFMPEG只需从Buffer3获取数据,而不用关心数据以何种方式得到

### 使用 `ffmpeg.input` 从声卡捕获音频数据 要通过 Python 的 `ffmpeg-python` 库实现从声卡捕获音频输入的功能,可以基于 FFmpeg 提供的命令行工具构建相应的 API 调用逻辑。以下是具体方法: #### 声卡捕获基础 FFmpeg 支持多种音频捕获方式,其中常见的有 DirectShow (dshow) ALSA 音频接口。DirectShow 主要在 Windows 平台上使用,而 ALSA 则适用于 Linux 系统。 对于 Windows 用户,可以通过 `-f dshow` 参数来指定虚拟声卡作为输入源[^1]。而对于 Linux 用户,则可借助 ALSA 或 PulseAudio 接口完成相同功能[^3]。 #### 实现代码示例 下面分别给出针对不同操作系统的解决方案及其对应的 Python 实现代码。 ##### 方法一:Windows 下使用 DirectShow 抓取声音 假设已经安装并配置好了名为 “virtual-audio-capturer” 的虚拟声卡设备,那么可以直接调用如下命令进行录音[^1]: ```python import ffmpeg input_stream = ffmpeg.input('audio=virtual-audio-capturer', f='dshow') output_file = 'captured_audio.mp3' stream = input_stream.output(output_file).run() ``` 此处需要注意的是,在实际运行前需确认目标系统已正确设置好所需的虚拟音频捕捉装置,并且该名称应与执行 `ffmpeg -list_devices true -f dshow -i dummy` 后显示的结果一致[^5]。 ##### 方法二:Linux 下使用 ALSA/PulseAudio 进行录制 在 Linux 中,可通过 ALSA 设备名访问物理或虚拟麦克风资源。例如,默认硬件路径可能形如 `hw:X,Y,Z` 形式表示具体的声卡编号及子设备索引位置;另外也可以采用更灵活的脉冲音频服务端点地址代替传统 ALSA 描述符[^4]: ```python import ffmpeg # 对于 ALSA 输入 input_alsa = ffmpeg.input('default', f='alsa') output_wav = 'out_also.wav' stream_alsa = input_alsa.output(output_wav).run() # 若改用 PulseAudio 取代 ALSA input_pulse = ffmpeg.input('pulse', f='pulse') output_pulsewav = 'out_pulse.wav' stream_pulse = input_pulse.output(output_pulsewav).run() ``` 以上脚本片段展示了两种主要情形下的处理流程——即当选用 ALSA 架构时传参为 `'default'` ,而在切换至 PulseAudio 场景下则改为 `'pulse'` 。同时还可以进一步自定义诸如采样率 (`ar`)、声道数目(`ac`)之类的属性值以满足特定需求[^4]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值