如何从RTP包的AP类型包,获取h265的PPS、SPS、VPS信息

ffmpeg播放rtp流,为了降低首开延迟,需要在SDP文件中指定PPS、SPS、VPS信息。抓包后发现wireshark无法解析AP包。需要自己进行AP包解析。RTP协议AP包格式如下:

根据如上信息,我们可以解析AP包,效果如下

  • 40 01,type=32,VPS(视频参数集)
  • 42 01,type=33,SPS(序列参数集)
  • 44 01,type=34,PPS(图像参数集)
  • 4E 01, type=39,SEI(补充增强信息)
  • 26 01,type=19,可能有RADL图像的IDR图像的SS编码数据 IDR
  • 02 01, type=01,被参考的后置图像,且非TSA、非STSA的SS编码数据
  • 46 01,type=35,分隔符,没用。

下图中红色部分是分隔符,橙色是VPS,黑色是SPS,黄色为PPS

SDP中的VPS等信息需要转换成base64。使用下面的函数可转换
#include <stdio.h>
#include <inttypes.h>
#include <math.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
#include <string>
#include <string.h>
#include <iostream>


#define AV_BASE64_SIZE(x)  (((x)+2) / 3 * 4 + 1)
#   define AV_RB32(x)                                \
    (((uint32_t)((const uint8_t*)(x))[0] << 24) |    \
               (((const uint8_t*)(x))[1] << 16) |    \
               (((const uint8_t*)(x))[2] <<  8) |    \
                ((const uint8_t*)(x))[3])
using namespace std;
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
{
    static const char b64[] =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    char *ret, *dst;
    unsigned i_bits = 0;
    int i_shift = 0;
    int bytes_remaining = in_size;

    if (in_size >= UINT_MAX / 4 ||
        out_size < AV_BASE64_SIZE(in_size))
        return NULL;
    ret = dst = out;
    while (bytes_remaining > 3) {
        i_bits = AV_RB32(in);
        in += 3; bytes_remaining -= 3;
        *dst++ = b64[ i_bits>>26        ];
        *dst++ = b64[(i_bits>>20) & 0x3F];
        *dst++ = b64[(i_bits>>14) & 0x3F];
        *dst++ = b64[(i_bits>>8 ) & 0x3F];
    }
    i_bits = 0;
    while (bytes_remaining) {
        i_bits = (i_bits << 8) + *in++;
        bytes_remaining--;
        i_shift += 8;
    }
    while (i_shift > 0) {
        *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
        i_shift -= 6;
    }
    while ((dst - ret) & 3)
        *dst++ = '=';
    *dst = '\0';

    return ret;
}

static int doLog = 0;
void hexDump(uint8_t* data,int len){
  if(doLog == 0)
    return;
  printf("[%d]",len);
  int pos = 0;
  uint8_t d = 0;
  while(pos<len){
    d = *(data+pos);
    printf("0x%02x,",(int)d);
    pos++;
  }
  printf("[%d]\n",len);
}
//sprop-vps=QAEMAf//AWAAAAMAkAAAAwAAAwBalZgJ; sprop-sps=QgEBAWAAAAMAkAAAAwAAAwBaoAeCAIh95ZWaSTK8BacIAAADAAgAAAMA8EA=; sprop-pps=RAHBcrRiQA==
//sprop-vps=DAH//wFgAAADALAAAAMAAAMAWqwJ; sprop-sps=AQFgAAADALAAAAMAAAMAWqAPCAPBY2uSRS9NQEBAQCA=; sprop-pps=wPLOcDs0
void getXPSfromAP(uint8_t* ap){
  int pos = 0;
  while(true){
    uint16_t hdr = (ap[pos+2]<<8)|(ap[pos+3]);
    int typ = (hdr>>9)&0x3f;
    int siz = (ap[pos+0]<<8)|(ap[pos+1])-2;
    switch(typ){
      case 32:
      { 
        char str_vps[100]={0};
        uint8_t* vps = (uint8_t*)malloc(siz);
        memcpy(vps,ap+pos+4,siz);
        av_base64_encode(str_vps,100,vps,siz);
        cout<<"sprop-vps="<<str_vps;
        hexDump(vps,siz);
        free(vps);
        break;
      }
      case 33:
      { 
        char str_sps[100]={0};
        uint8_t* sps = (uint8_t*)malloc(siz);
        memcpy(sps,ap+pos+4,siz);
        av_base64_encode(str_sps,100,sps,siz);
        cout<<"; sprop-sps="<<str_sps;
        hexDump(sps,siz);
        free(sps);
        break;
      }
      case 34:
      { 
        char str_pps[100]={0};
        uint8_t* pps = (uint8_t*)malloc(siz);
        memcpy(pps,ap+pos+4,siz);
        av_base64_encode(str_pps,100,pps,siz);
        cout<<"; sprop-pps="<<str_pps<<endl;
        hexDump(pps,siz);
        free(pps);
        return;
        break;
      }
      default:
        break;
    }
    pos += 4;
    pos += siz;
  }
}
int main(int argc, char *argv[]) {
  if(argc>=2){
    doLog = atoi(argv[1]);
  }
 
  uint8_t in[]={0x67, 0x42,0xc0,0x14,0xf4,0x0b,0x04,0xb4,0x20,0x00,0x00,0x03,0x00,0x20,0x00,0x00,0x03,0x03,0xd1,0xe2,0x85,0x54};
    char str_sps[100]={0};
    av_base64_encode(str_sps,100,in,22);
    cout<<"sps'sbasecode:"<<str_sps<<endl;
    uint8_t pps[]={0x68 ,0xce ,0x04 ,0xf2};
  char str_sps2[100]={0};
    av_base64_encode(str_sps2,100,pps,4);
    cout<<"pps'sbasecode:"<<str_sps2<<endl;
 
  uint8_t ap[] = {0x00,0x17,0x40,0x01,0x0c,0x01,0xff,0xff,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5a,0xac,0x09,0x00,0x22,0x42,
    0x01,0x01,0x01,0x60,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x5a,0xa0,0x0f,0x08,0x03,0xc1,0x63,0x6b,0x92,0x45,0x2f,
    0x4d,0x40,0x40,0x40,0x40,0x20,0x00,0x08,0x44,0x01,0xc0,0xf2,0xce,0x70,0x3b,0x34,0x00,0x09,0x4e,0x01,0xe5,0x04,0x00,0x00,0x70,0x00,0x80,0x00,
    0x1e,0x4e,0x01,0x89,0x18,0x3a,0x98,0x75,0x30,0x1d,0x4c,0x0b,0xb8,0x7d,0x00,0x40,0x74,0x3d,0x13,0x40,0x42,0x00,0x00,0x04,0xb0,0x00,0x00,0x03,0x00,0xc8,0x80};
  getXPSfromAP(ap);
  return 0;
}
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/307487.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MPI并行程序设计 —— C 和 fortran 环境搭建 openmpi 示例程序

1.安装环境 wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.6.tar.g tar zxf openmpi-4.1.6.tar.gz cd openmpi-4.1.6/ 其中 configure 选项 --prefix/.../ 需要使用绝对路径&#xff0c;例如&#xff1a; ./configure --prefix/home/hipper/ex_open…

【C++干货铺】STL中set和map的介绍和使用

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 序列式容器 关联式容器 键值对 树形结构的关联式容器 set set的介绍 set的使用 set的模板参数列表 set的构造 ​编辑 set的容量 set的删除和查找 mult…

4.16 构建onnx结构模型-And

前言 构建onnx方式通常有两种&#xff1a; 1、通过代码转换成onnx结构&#xff0c;比如pytorch —> onnx 2、通过onnx 自定义结点&#xff0c;图&#xff0c;生成onnx结构 本文主要是简单学习和使用两种不同onnx结构&#xff0c; 下面以 And 结点进行分析 方式 方法一&…

马斯克谈六西格玛:管理质量与火箭科学如何相辅相成

如果你问我&#xff0c;作为一个有志于送人类上火星的家伙&#xff0c;六西格玛管理有没有用&#xff1f;我会说&#xff0c;如果把火箭控制的精度与六西格玛得到的生产质量相比&#xff0c;你会发现两者都追求同一件事&#xff1a;接近零缺陷的完美。 六西格玛不只是一组工具…

【2023 CCF 大数据与计算智能大赛】基于TPU平台实现超分辨率重建模型部署 基于FSRCNN的TPU平台超分辨率模型部署方案

2023 CCF 大数据与计算智能大赛 基于TPU平台实现超分辨率重建模型部署 基于FSRCNN的TPU平台超分辨率模型部署方案 WELL 刘渝 人工智能 研一 西安交通大学 中国-西安 1461003622qq.com 史政立 网络空间安全 研一 西安交通大学 中国-西安 1170774291qq.com 崔琳、张…

MySQL报错:1366 - Incorrect integer value: ‘xx‘ for column ‘xx‘ at row 1的解决方法

我在插入表数据时遇到了1366报错&#xff0c;报错内容&#xff1a;1366 - Incorrect integer value: Cindy for column name at row 1&#xff0c;下面我演示解决方法。 根据上图&#xff0c;原因是Cindy’对应的name字段数据类型不正确。我们在左侧找到该字段所在的grade_6表&…

MySQL的日志管理以及备份和恢复

MySQL日志管理 mysql的日志默认保存位置为/usr/local/mysql/data vim /etc/my.cnf #开启二进制日志功能 vim /etc/my.cnf [mysqld]##错误日志&#xff0c;用来记录当MySQL启动、停止或运行时发生的错误信息&#xff0c;默认已开启 log-error/usr/local/mysql/data/mysql_…

RabbitMQ 核心概念(交换机、队列、路由键),队列类型等介绍

RabbitMQ 核心概念(交换机、队列、路由键)&#xff0c;队列类型等介绍 RabbitMQ 是一个消息队列系统&#xff0c;它的核心概念包括交换机&#xff08;Exchange&#xff09;、队列&#xff08;Queue&#xff09;和路由键&#xff08;Routing Key&#xff09;&#xff0c;它们一起…

shiro1.13认证流程核心-非框架整合版本

本案例测试使用的是shiro1.13.0最新版本测试 1、shiro概述&#xff1f; Apache Shiro是java的一个安全框架&#xff0c;能够实现&#xff1a;认证、授权、加密、会话管理、与Web集成、缓存等。 认证&#xff1a;本质就是判断你输入的用户名和密码跟数据库的是否相同。 授权&am…

售后客服日常回复必备的话术

致歉安抚通用 1.非常抱歉耽误您宝贵的时间了&#xff0c;这边给您查询一下&#xff0c;请稍等。 2.非常抱歉&#xff0c;给您添麻烦了。这边为您转接售后专员给您处理&#xff0c;请亲稍等。 3.影响到您的购物体验万分抱歉。 4.这边都会给您尽心解决的呢。 5.我非常理解您…

全新研发体系助力产品落地 传音控股成科技出海代表

一直以来&#xff0c;手机都被认为是所有新技术的最佳应用载体&#xff0c;尤其是在数字化、智能化时代&#xff0c;技术创新能力决定着手机厂商的生存与发展。 作为全球新兴市场手机行业的中坚力量之一&#xff0c;传音控股始终坚持以技术创新为驱动&#xff0c;围绕用户需求…

Airtest+Poco多设备并发自动化游戏测试框架(遇到的问题)

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…