这段代码实现了一个树莓派相机JPEG拍照应用的完整控制流程,其核心逻辑可分为四个阶段:
1. 初始化阶段
RPiCamJpegApp app;
StillOptions *options = app.GetOptions();
- 作用:创建相机应用实例,获取参数解析器
- 类比:就像打开手机相机APP时自动加载默认设置
2. 参数处理阶段
if (options->Parse(argc, argv)) {
if (options->Get().verbose >= 2)
options->Get().Print();
if (options->Get().output.empty())
throw std::runtime_error("output file name required");
}
- 关键检查:
- 解析命令行参数(如
--width 1920 --output photo.jpg) - 调试模式时打印参数详情(
verbose≥2) - 强制验证:输出文件名不能为空(否则抛异常)
- 解析命令行参数(如
- 设计思想:前置条件检查,确保后续逻辑能安全执行
3. 主业务逻辑
event_loop(app);
- 典型行为:
- 初始化摄像头硬件
- 循环捕获图像帧
- 按参数要求保存JPEG文件
- 处理用户中断信号(如Ctrl+C)
- 特点:这是整个应用最核心且可能抛出异常的模块
4. 异常安全处理
catch (std::exception const &e) {
LOG_ERROR("ERROR: *** " << e.what() << " ***");
return -1;
}
- 防护范围:覆盖从参数检查到主逻辑的所有异常
- 典型异常:
- 硬件访问失败(如相机被占用)
- 文件写入错误(如磁盘空间不足)
- 参数校验失败(如无效分辨率)
- 错误处理:记录日志 + 返回
-1(Unix风格错误码)
执行流程图解
graph TD
A[启动程序] --> B[创建相机实例]
B --> C{参数解析成功?}
C -->|是| D[调试信息打印]
D --> E{有输出文件名?}
E -->|是| F[进入主事件循环]
E -->|否| G[抛异常]
C -->|否| H[跳过主逻辑]
F --> I[正常退出 return 0]
G --> J[捕获异常]
J --> K[打印错误并返回-1]
设计亮点
-
防御式编程
- 通过
output.empty()检查避免文件写入冲突 - 异常处理覆盖所有关键操作
- 通过
-
调试友好
verbose分级控制日志详细程度- 参数打印功能快速确认运行时配置
-
符合Unix惯例
- 成功返回
0,失败返回-1 - 错误信息输出到标准错误流(假设
LOG_ERROR实现正确)
- 成功返回
典型使用场景
# 正常拍照(静默模式)
./rpicam_jpeg --output photo.jpg
# 调试模式(打印参数)
./rpicam_jpeg --output test.jpg --verbose 2 --width 1280
# 错误案例(触发异常)
./rpicam_jpeg # 缺少--output参数,程序报错退出
浙公网安备 33010602011771号