【obs-studio开源项目从入门到放弃】obs媒体源 ffmpeg_source 分析

本文深入解析OBS(Open Broadcasting Software)媒体源的创建、音视频帧输出及控制流程。OBS基于ffmpeg库实现媒体源播放,通过media-playback库封装ffmpeg的API。媒体源创建调用obs_source_create,解码后的视频帧通过mp_media_next_video输出,音频帧通过mp_media_next_audio输出。控制操作如播放、暂停、seek等由相应回调函数处理。整体处理简单高效,适合学习ffmpeg解封装。


前言

obs支持添加各种容器格式的视频文件,音频文件(mp4、flv、mp3、ts),也支持添加网络流(rtmp,srt,rtsp,udp)。本质上obs是基于ffmpeg的libavformat库提供解码能力播放媒体视频。只要是obs的依赖ffmpeg库支持的协议都可以作为媒体源添加。
通过下面命令查看ffmpeg支持的协议

.\ffmpeg.exe -protocols		//打印ffmpeg支持的协议

媒体源的创建

媒体源的创建有多种方式,可以直接将视频文件直接拖拽进obs主窗口,可以在主窗口右键添加媒体源,也可以复制当前存在的媒体源。不管哪种方式创建媒体源最后的入口都是obs_source_create,这是libobs提供的创建源的api,如果进行obs二次开发添加源的入口也都是走这个api。下面贴一下拖拽方式创建媒体源的调用堆栈。

>	obs-ffmpeg.dll!ffmpeg_source_update(void * data, obs_data * settings)456	C
 	obs-ffmpeg.dll!ffmpeg_source_create(obs_data * settings, obs_source * source)613	C
 	obs.dll!obs_source_create_internal(const char * id, const char * name, obs_data * settings, obs_data * hotkey_data, bool private, unsigned int last_obs_ver)387	C
 	obs.dll!obs_source_create(const char * id, const char * name, obs_data * settings, obs_data * hotkey_data)416	C
 	obs64.exe!OBSBasic::AddDropSource(const char * data, OBSBasic::DropType image)176	C++
 	obs64.exe!OBSBasic::dropEvent(QDropEvent * event)280	C++
 	[外部代码]	
 	obs64.exe!run_program(std::basic_fstream<char,std::char_traits<char>> & logFile, int argc, char * * argv)2143	C++
 	obs64.exe!main(int argc, char * * argv)2839	C++
 	obs64.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal)97	C++

媒体源输出音频帧和视频帧

media-playback 封装了操作媒体源的api

obs对媒体源的操作都封装到了media-playback.lib,通过media.h里的函数的命名就可以看出。

//媒体源的初始化和销毁
extern bool mp_media_init(mp_media_t *media, const struct mp_media_info *info);
extern void mp_media_free(mp_media_t *media);

//媒体源的控制 播放 停止 暂停 获取当前播放时间 快进快退
extern void mp_media_play(mp_media_t *media, bool loop, bool reconnecting);
extern void mp_media_stop(mp_media_t *media);
extern void mp_media_play_pause(mp_media_t *media, bool pause);
extern int64_t mp_get_current_time(mp_media_t *m);
extern void mp_media_seek_to(mp_media_t *m, int64_t pos);

通过下面创建媒体源的调用堆栈可以看到,最终都调用到了media-playback的里面。

 	obs-ffmpeg.dll!mp_media_init_internal(mp_media * m, const mp_media_info * info)797	C
 	obs-ffmpeg.dll!mp_media_init(mp_media * media, const mp_media_info * info)834	C
 	obs-ffmpeg.dll!ffmpeg_source_open(ffmpeg_source * s)319	C
 	obs-ffmpeg.dll!ffmpeg_source_update(void * data, obs_data * settings)453	C
 	obs-ffmpeg.dll!ffmpeg_source_create(obs_data * settings, obs_source * source)613	C

一图抵千言,贴一下我准备的xmind截图。
media-playback
可以看到在mp_media_init_internal函数里面创建了一个mp_media_thread_start线程来执行音视频的解码,对ffmpeg解封装流程比较熟悉,这里面的代码就很好理解了,这里便不再赘述。有时间单独做一个ffmpeg系列的专栏,详细说一下ffmpeg解封装,编解码的api调用逻辑。

mp_media_next_video() 输出解码后的视频帧

解码后的视频帧通过函数mp_media_next_video调用在ffmpeg_source_open里面绑定回调函数get_audio,最终通过 obs_source_output_video() 插入到libobs的视频帧缓存队列,等待视频渲染线程取走做渲染。媒体源属于异步输出视频帧,output_flags包含OBS_SOURCE_ASYNC_VIDEO属性。

static void get_frame(void *opaque, struct obs_source_frame *f)
{
	struct ffmpeg_source *s = opaque;
	obs_source_output_video(s->source, f);
}

mp_media_next_audio() 输出解码后的音频帧

解码后的音频帧通过函数 mp_media_next_audio() 调用在ffmpeg_source_open里面绑定回调函数get_audio,最终通过obs_source_output_audio输出到libobs的音频帧缓冲队列,等待音频编码线程取走做编码发送。

static void get_audio(void *opaque, struct obs_source_audio *a)
{
	struct ffmpeg_source *s = opaque;
	obs_source_output_audio(s->source, a);

	if (!s->is_local_file && os_atomic_set_bool(&s->reconnecting, false))
		FF_BLOG(LOG_INFO, "Reconnected.");
}

媒体源的控制

控制媒体源的暂停,播放,还有seek操作都比较简单。阅读下面绑定的函数很容易理解。

struct obs_source_info ffmpeg_source = {
	.media_play_pause = ffmpeg_source_play_pause,	//控制暂停
	.media_restart = ffmpeg_source_restart,			//重新播放
	.media_stop = ffmpeg_source_stop,				//停止播放
	.media_get_duration = ffmpeg_source_get_duration,//获取播放媒体源的总时长
	.media_get_time = ffmpeg_source_get_time,		//获取当前播放时机
	.media_set_time = ffmpeg_source_set_time,		// seek操作
	.media_get_state = ffmpeg_source_get_state,		//获取当前播放状态
}

总结

obs的媒体源整个处理比较简单,底层基于ffmpeg的api做视频的解封装,只用了一个线程完成了音视频的解码输出,解码完成后通过libobs的api添加到音视频相应的队列,等待音视频各自的线程取走渲染播放。media-playback是一个非常好的可以学习ffmepg解封装api的一个小项目。

以上都是个人工作当中对obs-studio开源项目的理解,难免有错误的地方,如果有欢迎指出。

若有帮助幸甚。


技术参考

  1. 视频技术参考: https://ke.qq.com/course/3202131?flowToken=1040950
08-10
<think>首先,用户的问题是关于在Ubuntu上运行OBS(Open Broadcaster Software)时出现的两个错误:"Attempted path" 和 "Segmentation fault"。用户提到了参考站内引用,这些引用是关于类似问题的案例,比如库冲突导致的Segmentation fault。 我的回答需要: - 使用中文 - 结构清晰,逐步解决问题 - 保证回答真实可靠 - 在行内数学表达式使用$...$格式,独立公式使用$$...$$格式 - 生成相关问题 - 在引用段落末尾添加引用标识 用户提供的引用: - [^1]: 关于export LD_LIBRARY_PATH导致Segmentation fault的解决方案,指出库冲突问题。 - [^2]: 一个Segmentation fault例子,涉及XDG_RUNTIME_DIR未设置- [^3]: 在ROS中运行ORB-SLAM3时出现Segmentation fault,可能与库或路径问题相关。 - [^4]: 移植OpenCV时出现Segmentation fault,最终通过更改图片格式解决。 - [^5]: 关于编译旧Linux版本的引用,可能不直接相关。 用户的问题核心是解决OBS的路径错误和Segmentation fault。OBS是开源的直播软件,常见问题包括依赖库冲突、环境变量设置不当等。 结构化回答: 1. **理解问题**:确认用户遇到的错误。用户说"Attempted path"错误,可能是指OBS尝试访问某个路径失败;Segmentation fault通常是内存访问错误。 2. **常见原因分析**: - 路径错误:可能涉及文件路径、环境变量如LD_LIBRARY_PATH。 - Segmentation fault:可能由于库版本冲突、内存问题等。 3. **解决方案步骤**: - 检查环境变量:参考引用[^1],避免使用export LD_LIBRARY_PATH如果导致冲突。 - 设置运行时目录:参考引用[^2],设置XDG_RUNTIME_DIR。 - 更新和安装依赖:确保所有依赖库正确安装。 - 使用AppImage或Flatpak:OBS通常提供这些格式,避免系统库冲突。 - 调试工具:使用gdb或valgrind诊断Segmentation fault。 4. **生成相关问题**:在回答末尾添加相关问题,帮助用户深入。 确保回答真实可靠:基于OBS官方文档和Ubuntu社区知识。OBS常见安装方式包括PPA、Snap或源码编译。 步骤计划: 1. 介绍问题:简要说明错误。 2. 逐步解决: - 解决路径错误:检查路径设置- 解决Segmentation fault:检查库冲突、更新系统。 3. 提供命令示例。 4. 添加相关问题。 引用处理:在回答中,如果引用参考内容,末尾添加[^1]等。但用户提供的引用是站内的,我需要自然地融入。 最终回答结构: - 开头:确认问题。 - 步骤1:解决"Attempted path"错误。 - 步骤2:解决Segmentation fault。 - 步骤3:其他建议。 - 结尾:生成相关问题。</think>### Ubuntu运行OBS命令行报错"Attempted path"和"Segmentation fault"解决方案 在Ubuntu上运行OBS(Open Broadcaster Software)时,出现"Attempted path"错误和"Segmentation fault"是常见问题,通常由路径配置错误或库冲突引起。下面我将逐步解释原因并提供解决方案。整个过程基于OBS官方文档和Ubuntu社区经验,确保可靠。请按顺序操作,避免跳过步骤。 #### 步骤1: 解决"Attempted path"错误 "Attempted path"错误通常表示OBS无法找到必要的文件路径(如配置文件、资源文件或插件)。这可能是由于环境变量未正确设置或安装路径不一致导致。 - **检查环境变量**: 确保OBS的关键路径被正确设置。在终端运行以下命令,检查输出是否包含OBS的安装路径(通常是`/usr/bin/obs`或`/opt/obs-studio/bin/obs`): ```bash echo $PATH ``` 如果路径缺失,手动添加它(假设OBS安装在`/opt/obs-studio/bin`): ```bash export PATH=$PATH:/opt/obs-studio/bin # 临时生效,重启后失效 ``` 要使永久生效,编辑`~/.bashrc`文件,添加相同行,然后运行`source ~/.bashrc`。 - **验证配置文件路径**: OBS需要访问`~/.config/obs-studio`目录。确保该目录存在且有权写入: ```bash mkdir -p ~/.config/obs-studio # 创建目录(如果不存在) chmod 755 ~/.config/obs-studio # 设置权限 ``` 如果错误提示特定文件路径(如`Attempted path: /path/to/file`),手动创建缺失的文件或目录。 - **重装OBS**: 路径错误可能源于不完整的安装。卸载后重新安装最新版OBS(推荐使用官方PPA): ```bash sudo apt remove obs-studio --purge # 卸载 sudo add-apt-repository ppa:obsproject/obs-studio # 添加官方PPA sudo apt update sudo apt install obs-studio # 安装 ``` 完成此步骤后,运行`obs`命令测试是否解决路径错误。如果问题依旧,检查终端输出中的具体路径提示。 #### 步骤2: 解决Segmentation fault Segmentation fault(段错误)表示程序访问了非法内存地址,常见于库冲突、环境变量问题或硬件兼容性错误。参考引用[^1],这通常与`LD_LIBRARY_PATH`设置不当导致的库冲突相关[^1]。 - **检查并重置`LD_LIBRARY_PATH`**: 在终端查看当前设置: ```bash echo $LD_LIBRARY_PATH ``` 如果输出非空,可能与其他库冲突。临时清空它以测试: ```bash unset LD_LIBRARY_PATH # 清空变量 obs # 重新运行OBS ``` 如果Segmentation fault消失,说明冲突存在。永久解决方案:编辑`~/.bashrc`或`~/.profile`,注释掉或删除`export LD_LIBRARY_PATH=...`行,然后运行`source ~/.bashrc`。 - **设置运行时目录**: 引用[^2]显示,未设置`XDG_RUNTIME_DIR`可能导致段错误[^2]。确保该变量正确设置: ```bash export XDG_RUNTIME_DIR=/run/user/$UID # 临时设置 echo 'export XDG_RUNTIME_DIR=/run/user/$UID' >> ~/.bashrc # 永久设置 source ~/.bashrc ``` - **更新系统和依赖库**: 库版本不匹配是常见原因。更新所有包并安装OBS依赖: ```bash sudo apt update && sudo apt upgrade # 更新系统 sudo apt install build-essential libgl1-mesa-dev libx11-dev # 安装关键依赖 ``` 安装显卡驱动(Segmentation fault可能与图形驱动相关): ```bash sudo ubuntu-drivers autoinstall # 自动安装推荐驱动 sudo reboot # 重启生效 ``` - **使用调试工具诊断**: 如果以上无效,使用`gdb`捕获错误: ```bash sudo apt install gdb # 安装调试器 gdb obs # 启动调试 run # 在gdb中运行OBS ``` 当Segmentation fault发生时,输入`bt`查看堆栈跟踪,定位出错模块。常见原因包括OpenGL或FFmpeg库冲突(参考引用[^3]中的类似案例[^3])。 #### 步骤3: 其他建议 - **使用AppImage格式**: 避免系统库冲突,下载OBS的AppImage版本(独立打包): 1. 从[OBS官网](https://obsproject.com/download)下载AppImage文件。 2. 赋予执行权限:`chmod +x OBS-*.AppImage` 3. 直接运行:`./OBS-*.AppImage` - **检查硬件加速**: 在OBS设置中禁用硬件编码测试: 1. 启动OBS图形界面:`obs` 2. 转到"Settings" > "Output",将"Encoder"改为"Software (x264)"。 - **日志分析**: 运行OBS时启用详细日志: ```bash obs --verbose # 输出详细日志 ``` 检查日志中是否有"library not found"或"failed to load"提示,对应安装缺失库。 #### 验证解决方案 完成所有步骤后,运行`obs`命令测试。如果问题解决,建议定期更新系统。如果Segmentation fault持续,可能是硬件问题(如内存故障),运行内存测试: ```bash sudo apt install memtester memtester 1G 1 # 测试1GB内存,运行1次 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值