# ema-media-shm-stream
**Repository Path**: ematech/ema-media-shm-stream
## Basic Information
- **Project Name**: ema-media-shm-stream
- **Description**: 基于 EMA Media Service 共享内存订阅机制,实现完整的数据流消费链路:
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-04-24
- **Last Updated**: 2026-06-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# shm_stream_demo - 共享内存数据流订阅 + 硬解码 Demo
## 功能说明
基于 EMA Media Service 共享内存订阅机制,实现完整的数据流消费链路:
**gRPC 订阅 → 共享内存接收 → 硬解码 → 输出保存**
## 目录结构
```
shm_stream_demo/
├── CMakeLists.txt # CMake 构建配置
├── build.sh # 本地构建脚本
├── docker_compile.sh # Docker 交叉编译脚本
├── app.conf # 打包配置(构建时自动复制到 release/)
├── src/main.cpp # 主程序
├── proto/ # Proto 文件
│ ├── mediaResult.proto
│ ├── aipaasCommon.proto
│ ├── github.com/gogo/protobuf/gogoproto/gogo.proto
│ └── ema_ipc/ # ema_ipc 内部 proto
├── include/ # 头文件
│ ├── xmpp/ # XMPP 硬解码库头文件
│ ├── ema_ipc/ # ema_ipc 共享内存库头文件
│ ├── grpc/ # gRPC 头文件
│ ├── grpc++/ # gRPC++ 头文件
│ └── boost/ # Boost 头文件
├── tool/run.sh # 发布包运行脚本
├── lib/ascend310b1/ # 预编译库
│ ├── libxmpp.so # XMPP 硬解码库
│ ├── libema_ipc.so # 共享内存 IPC 库
│ ├── libgrpc++.so # gRPC 库
│ ├── libprotobuf.so # Protobuf 库
│ ├── libboost_*.so # Boost 库
│ └── liblog4cpp.so # log4cpp 库
└── conf/
└── ipc.pb.conf # ema_ipc 配置文件
```
## 构建
### 本地构建(需要安装依赖)
```bash
./build.sh
```
### Docker 交叉编译(推荐)
```bash
./docker_compile.sh -p ascend310-gcc10.3.0-sdk7.0.rc1 -e ./build.sh
```
### 构建托管服务 Docker 镜像
使用 `packet.sh` 将编译好的程序打包为符合 PaaS 平台规范的 Docker 镜像。`app.conf` 位于项目根目录,`build.sh` 会自动将其复制到 `release/`。
**app.conf 格式:**
```ini
app_name=shm_stream_demo
version=1.0.0
command=shm_stream_demo -u rtsp://10.1.32.193:8554/rtsp/stream10 -W 1280x720
```
**配置目录示例(release/):**
```
release/ # 由 build.sh 自动生成
├── app.conf # 从项目根目录自动复制(不会复制到镜像)
├── bin/
│ └── shm_stream_demo # 二进制
├── lib/
│ ├── libxmpp.so # XMPP 硬解码库
│ ├── libema_ipc.so # 共享内存 IPC 库
│ └── libipc_proto.so # IPC proto 库
└── run.sh # 运行脚本
```
**用法:**
```bash
# 使用 release 目录打包
./packet.sh -d ./release
# 使用自定义目录,命令行覆盖版本号
./packet.sh -d ./deploy -v 2.0.0
```
**参数说明:**
| 参数 | 说明 |
|------|------|
| `-d, --dir
` | 应用配置目录(必选,目录下需含 app.conf) |
| `-v, --version ` | 镜像版本标签(覆盖 app.conf 中的 version) |
| `-h, --help` | 显示帮助 |
**app.conf 配置项:**
| 配置项 | 说明 |
|--------|------|
| `app_name` | 应用名称,用于生成镜像名和容器名 |
| `version` | 版本号 |
| `command` | 启动命令(支持带参数) |
**镜像规范:**
- 镜像名称:`ai/faas/app/:`
- 基础镜像:`ubuntu:22.04` (arm64)
- 配置目录内容平铺复制到 `/usr/local/`
- docker-compose.yml(含 Ascend 硬件设备映射)以 base64 编码嵌入镜像 LABEL
**前置条件:**
1. 配置目录下存在 `app.conf` 且包含 `app_name`、`version`、`command`
2. Docker 可用且支持 arm64 架构(如不支持可运行 `docker run --rm --privileged tonistiigi/binfmt --install arm64`)
**下一步:**
```bash
# 检查镜像
docker inspect ai/faas/app/shm-stream:1.0.0
# 推送镜像
docker push ai/faas/app/shm-stream:1.0.0
```
## 运行
### 使用发布包运行(推荐)
构建完成后,`release/` 目录即为可部署的发布包:
```
release/
├── run.sh # 运行脚本(自动设置环境变量)
├── bin/
│ └── shm_stream_demo
└── lib/
└── *.so
```
```bash
# 编辑 run.sh 修改参数后直接运行
cd release
./run.sh
```
### 手动运行(开发调试)
```bash
cd release
# 基本用法:通过 gRPC 订阅(媒体服务地址由 FoundationService 自动发现)
./bin/shm_stream_demo -u rtsp://10.1.32.193:8554/rtsp/stream10 -W 1280x720
# 保存解码后的帧到文件
./bin/shm_stream_demo -u rtsp://10.1.32.193:8554/rtsp/stream10 -o output.yuv -n 100 -W 1280x720
# 指定已有的共享内存通道(跳过 gRPC)
./bin/shm_stream_demo -c channel_name_123 -o output.yuv -n 100
# 调试模式
./bin/shm_stream_demo -u rtsp://10.1.32.193:8554/rtsp/stream10 -W 1280x720 -D
```
## 参数说明
| 参数 | 说明 | 默认值 |
|------|------|--------|
| `-u, --url` | 视频源地址(必填,除非指定 -c) | - |
| `-o, --output` | 解码后输出文件路径 | 无 |
| `-n, --frame-count` | 接收帧数 | -1(无限) |
| `-c, --channel` | 共享内存 channel_name | 无 |
| `-W, --size` | 视频分辨率(如 1280x720) | 1920x1080 |
| `-D, --debug` | 打印每帧详细信息 | false |
## 输出文件播放
解码输出为 NV12 格式的 YUV 文件,可用 ffplay 播放:
```bash
ffplay -f rawvideo -pixel_format nv12 -video_size 1920x1080 output.yuv
```
## 数据流说明
1. **gRPC 订阅**:调用 `SubscribeSourceData` 获取 channel_name
2. **共享内存接收**:通过 ema_ipc 接收 H.264/H.265 编码流
3. **硬解码**:XMPP 解码器将编码流解码为 NV12 帧
4. **输出保存**:将解码帧保存为 YUV 文件
## 关键映射
| Proto PixelFormat | XMPP VFormat |
|-------------------|--------------|
| PIX_FORMAT_H264 (19) | XMPP_VFORMAT_H264 (220) |
| PIX_FORMAT_H265 (20) | XMPP_VFORMAT_H265 (221) |
## 注意事项
1. channel_name 必须与服务端发布的 stream_name 完全一致
2. XmppVFrame 的 private_data 必须设为 NULL,private_flag 必须设为 0
3. xmpp_init() 必须在所有 XMPP 操作之前调用
4. xmpp_quit() 必须在程序退出时调用