FFmpeg常用指令记录sdp中提取sps/pps信息sps/pps(STAP-A解析)
Author:Peter
Location:FZU
Date: 2022-04-15
:如人饮水,冷暖自知。
ffmpeg编码/推流指令,ffprobe分析H264码流指令。win10系统,git bash终端操作(可使用linux相关指令)。
文章目录
- 1.ffmpeg利用x264编码YUV文件为H264
- 2.ffmpeg通过RTP封包推送H264码流
- 3.ffprobe分析h264文件指令
1.ffmpeg利用x264编码YUV文件为H264
- 将yuv420压缩成h264 -r:帧率,-g:GOPsize,-bf:B帧数量,-b:v 编码速率,-bufsize:码率控制缓冲区大小
./ffmpeg.exe -s 1920x1080 -i ParkScene_1920x1080.yuv -c:v libx264 -r 25 -g 50 -bf 0 -b:v 2000k -bufsize 2500k ParkScene_in.h264
2.ffmpeg通过RTP封包推送H264码流
注意事项,ffmpeg推送rtp流,IDR帧前不像Live555会采用两个packet封装sps/pps,而是直接一个STAP-A打包方式将sps及pps一同并入一个packet,即一个IDR帧前只含有一个sps&pps信息的packet,如下图抓包显示。
./ffmpeg.exe -re -i ParkScene_in.h264 -an -c copy -f rtp -ssrc 10 rtp://127.0.0.1:9900?pkt_size=1316 > 1.sdp
- ffmpeg 推RTP流,IDR帧中sps/pps抓包信息
开头十六进制18的后五位二进制为11000(十进制为24,属于STAP-A封包),即00 1a为第一个nalu(sps)[67 64… 92 40]的长度,00 05为第二个nalu(pps)[68 eb cc b2 2c]的长度。固接收端解析STAP-A包时,需要将18 00 1a 替换成00 00 00 01,00 05替换成00 00 00 01,记00 00 00 01为一个nalu的起始码。
- 接收端解析STAP-A(sps/pps)
#include<iostream>
#include<string>
#include<vector>using namespace std;union LENGTH //可以采用联合体,共用内存空间,length与byte[2]
{uint16_t length;uint8_t byte[2];
};//0x00 0x1a 0000 0000 0001 1010 = 26
void testSTAP_A()
{char sps_pps[] = { 0x18,0x00,0x1a,0x67,0x64,0x00,0x28,0xac,0xb2,0x00,0xf0,0x04,0x4f,0xcb,0x08,0x00,0x00,0x03,0x00,0x08,0x00,0x00,0x03,0x01,0x90,0x78,0xc1,0x92,0x40,0x00,0x05,0x68,0xeb,0xcc,0xb2,0x2c};int sps_length = 0;int pps_length = 0;//电脑是小端存储,地址低位存放数字低位,这样转过来为0x1a,0x00,0x00,0x00 十进制为26for (int i = 2, j = 0; i >= 1; --i, ++j)memcpy((char*)&sps_length + j, sps_pps + i, 1);cout << "sps_length=" << sps_length << endl;#if 1 //采用联合体计算sps长度,也要考虑到小端存储0x00 0x1a (0x1a在低地址)LENGTH sps;for (int i = 0; i < 2; ++i){sps.byte[i] = sps_pps[2 - i];}cout << sps.length << endl;#endif pps_length = sizeof(sps_pps) - sps_length - 5;//电脑是小端存储,地址低位存放数字低位,这样转过来为00 00 00 01uint32_t start_code = 0x01000000;vector<char> parse_sps_pps(sizeof(sps_pps) + 2 * 4 - 5);memcpy(parse_sps_pps.data(), &start_code, 4);memcpy(parse_sps_pps.data() + 4, sps_pps + 3, sps_length);memcpy(parse_sps_pps.data() + 4 + sps_length, &start_code, 4);memcpy(parse_sps_pps.data() + 8 + sps_length, sps_pps + 5 + sps_length, pps_length);
}int main()
{testSTAP_A();return 0;
}
- 指令生成的sdp信息:
SDP:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 58.76.100
m=video 9900 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAKKyyAPAET8sIAAADAAgAAAMBkHjBkkA=,aOvMsiw=; profile-level-id=640028
- 提取sdp中的sps/pps信息(base64编码,逗号是分割sps,pps)
sprop-parameter-sets=Z2QAKKyyAPAET8sIAAADAAgAAAMBkHjBkkA=,aOvMsiw=
其中sps信息: Z2QAKKyyAPAET8sIAAADAAgAAAMBkHjBkkA=
pps信息: aOvMsiw=
- C/C++代码提取sps/pps
#include <iostream>
#include <fstream>
#include <string>using namespace std;int main()
{ifstream inf("..\\ffmpeg_bin\\1.sdp");string oneline;string sps_sdp;string pps_sdp;string sps_pps_sdp;int sps_start,pps_start,pps_end;while (true){getline(inf, oneline);if (inf.eof() == true)break;cout << oneline << "\n";if ((sps_start = oneline.find("-sets=")) >0 && (pps_end = oneline.find("; profile")) >0 ){sps_start += 6;sps_pps_sdp.assign(oneline.data() + sps_start, oneline.data() + pps_end);}}if ((pps_start = sps_pps_sdp.find(",")) > 0){sps_sdp.assign(sps_pps_sdp.data(), sps_pps_sdp.data() + pps_start);pps_sdp.assign(sps_pps_sdp.data() + pps_start + 1, sps_pps_sdp.data() + sps_pps_sdp.size());cout << "sps:"<<sps_sdp << "\t" <<"pps:"<< pps_sdp << endl;}return 0;
}//----------------运行结果如下:----------------------
SDP:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 58.76.100
m=video 9900 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAKKyyAPAET8sIAAADAAgAAAMBkHjBkkA=,aOvMsiw=; profile-level-id=640028sps:Z2QAKKyyAPAET8sIAAADAAgAAAMBkHjBkkA= pps:aOvMsiw=
3.ffprobe分析h264文件指令
- 查看h264码流I/B/P帧分布
./ffprobe.exe -v error -show_frames ParkScene_in.h264 | grep "pict_type"
- 统计h264码流总帧数
./ffprobe.exe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 ParkScene_in.h264
- 查看h264码流信息
./ffprobe.exe -v error -show_streams ParkScene_in.h264
has_b_frames=0意味着264码流中无B帧。
FFmpeg常用指令记录sdp中提取sps/pps信息sps/pps(STAP-A解析)相关推荐
- Git 常用指令记录
Git 常用指令记录 创建代码库 提交代码 查看修改和撤销 分支用法 tag 版本控制 创建代码库 git init 提交代码 添加需要提交的文件 第一种,添加单个文件 git add [name] ...
- ffmpeg教程 如何从视频中提取音频文件?
今天用ffmpeg实现第一个功能,从视频文件中提取音频,生成mp3文件.代码很简单,只要拼接好正确的参数就行了. 传送门 ffmpeg教程 如何从视频中提取音频文件?
- 从FFmpeg 4. 2源码中提取dshow mjpeg code步骤
之前在https://blog.csdn.net/fengbingchun/article/details/103735560 中介绍过在Windows上通过vs2017编译FFmpeg源码进行单步调 ...
- Mysql中提取某列信息的一些函数方法
Mysql 学习笔记 文章目录 Mysql 学习笔记 前言 一.关于提取某列信息的一些函数方法 二.使用例子 1.数据信息 2.分别用这四种方法实现 总结 前言 提示: 写这篇博客是为了整理Mysql ...
- Git常用指令——持续补充中
Git项目代码提交下载流程 按如下顺序操作即可: 1. git init--创建/初始化仓库 2. Git clone --拉取远程仓库到本地 3. git status--查看工作区状态 4. gi ...
- Hive 常用指令记录
一.Hive基本概念 1.1 hive是什么 hive是基于hadoop的一个数仓分析工具,hive可以将hdfs上存储的结构化的数据,映射成一张表,然后让用户写HQL(类SQL)来分析数据 tel ...
- conda常用指令-持续更新中
conda常用命令 激活环境 列出所有环境 激活环境 conda activate 环境名称 列出所有环境 conda info --envs
- Ubuntu18常用指令集合(更新中)
GPU使用情况 watch -n -0.1 nvidia-smi 每隔0.1s刷新一次 watch -n -0.1 -d nvidia-smi 每隔0.1s刷新一次,带光标指示变化的数值
- 从mpeg ts文件中提取I帧(3):pes包的解析
本系列的第一篇文章讲解了如何把ts包拼装为pes包,本章主要讲解如何解析pes包. 一.pes包的格式如下图所示: 二.相关字段解析 packet_start_code_prefix ...
- adb+Frida+模拟器抓包的常用命令记录
目录 adb的常用指令 显示系统中全部设备 开启ADB服务 关闭ADB服务 连接设备 断开设备 超级用户权限,手机需要root或者eng模式 从adb取文件到电脑上 烧写文件到手机上 安装apk 卸载 ...
最新文章
- Markdown 修改图片的尺寸
- 干货丨一文看懂什么是“自然语言处理”
- Mysql定时执行任务实现方法
- python 3.6.5编译安装_Linux系统安装Python3.6.5
- 基于json-lib.jar包Json实例程序
- Vue常用经典开源项目
- Linux内核学习笔记(2)-- 父进程和子进程及它们的访问方法
- 硬件常见物料识别和单位换算
- Java后台+微信小程序实现推送 “服务通知”
- 链式存储结构的线性表
- Chrome浏览器(油猴子)插件安装使用教程
- SGM—代价聚合学习笔记
- 武警部队公安应急人防安监三维可视化交互电子沙盘方案书
- 电脑显示黑屏但是鼠标能动怎么处理?
- 云速美建站手机端使用百度app打开手机端网站闪退的问题
- Mybatis最拿得出手的功能之一 SpringBoot整合Mybatis-Plus 实战之动态SQL
- Java011-数组及其常见问题
- 英语FieldyellowStone田黄石fieldyellowstone单词
- IBM powerVC云管平台
- 气动调节阀的结构特点