AMFObject 数据格式浅析

amf.h中关于 AMFObject 是这样的定义的:

 typedef struct AMFObject
  {
    int o_num;
    struct AMFObjectProperty *o_props;
  } AMFObject;

有里面变量可知 o_num 代表 o_props的个数;

在rtmp.c里有这样一段使用在

static int HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize)
{
    AMFObject obj;
    AVal method;
    AVal method11;
    int txn;
    int ret = 0, nRes;
    if (body[0] != 0x02)        /* make sure it is a string method name we start with */
    {
        //RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet", __FUNCTION__);
        return 0;
    }

    nRes = AMF_Decode(&obj, body, nBodySize, FALSE);
    if (nRes < 0)
    {
        //RTMP_Log(RTMP_LOGERROR, "%s, error decoding invoke packet", __FUNCTION__);
        return 0;
    }

   AMF_Dump(&obj);   AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method);
    .....
  .....
}

在此函数内 AMFObject obj;通过 nRes = AMF_Decode(&obj, body, nBodySize, FALSE); 会对body进行AMF解码相当于给obj进行赋值,然后通过AMF_Dump(&obj) 应该是进行一个解析?(最下面会贴出该函数的源码)

经过AMF_Dump()之后,会获通过 AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method); 获取信令的操作。当然也可以自定义他们的操作,类似于:

static const AVal av_NetStream_Pause_Notify = AVC("NetStream.Pause.Notify");
static const AVal av_NetStream_Play_UnpublishNotify = AVC("NetStream.Play.UnpublishNotify");
//................

下面代码会根据method的内容进行相应的操作。
-----------------------------------------------

扯的有点偏了,这里还是 讲AMFObject 上面的操作经过抓包可以看一下大致的内容:

===================================================

由包里的内容此次信令操作为自定义的“NoticeNotify”,而obj相当于一个容器,里面就有上面标识的3项内容,也就是根据AMFObject 的数据结构可知:

o_num 个数为3 项 o_props 内容。而 o_props 的数据结构为:

typedef struct AMFObjectProperty
  {
    AVal p_name;
    AMFDataType p_type;
    union
    {
      double p_number;
      AVal p_aval;
      AMFObject p_object;
    } p_vu;
    int16_t p_UTCoffset;
  } AMFObjectProperty;

其中 o_props 里有个“联合”数据结构成员,从上面抓包的内容来看其中的三项,也很好的解释了其中三项的内容。

第一项:type 为string 对应 AVal 类似于 key-value

第二项:type 为Number 对应 double。

第三项:type 也为string 对应 AVal。

这样来看如果想取obj里的内容就比较好取了。

其中obj的成员 o_props 就是一个类似数组,在操作的时候可以 obj->o_props[index];

或者再细一点就是 obj->o_props[index].p_type;

=====================================

总结的比较乱,因为现在对amf还不是很了解,不过对于amf真的可以花些时间去分析一下它的博大精深。

再此贴一下AMF_Dump()的源码:

void
AMFProp_Dump(AMFObjectProperty *prop)
{
    char strRes[256];
    char str[256];
    AVal name;

    if (prop->p_type == AMF_INVALID)
    {
        //RTMP_Log(RTMP_LOGDEBUG, "Property: INVALID");
        return;
    }

    if (prop->p_type == AMF_NULL)
    {
        //RTMP_Log(RTMP_LOGDEBUG, "Property: NULL");
        return;
    }

    if (prop->p_name.av_len)
    {
        name = prop->p_name;
    }
    else
    {
        name.av_val = "no-name.";
        name.av_len = sizeof("no-name.") - 1;
    }
    if (name.av_len > 18)
        name.av_len = 18;

    snprintf(strRes, 255, "Name: %18.*s, ", name.av_len, name.av_val);

    if (prop->p_type == AMF_OBJECT)
    {
        //RTMP_Log(RTMP_LOGDEBUG, "Property: <%sOBJECT>", strRes);
        AMF_Dump(&prop->p_vu.p_object);
        return;
    }

    switch (prop->p_type)
    {
    case AMF_NUMBER:
        snprintf(str, 255, "NUMBER:\t%.2f", prop->p_vu.p_number);
        break;
    case AMF_BOOLEAN:
        snprintf(str, 255, "BOOLEAN:\t%s",
            prop->p_vu.p_number != 0.0 ? "TRUE" : "FALSE");
        break;
    case AMF_STRING:
        snprintf(str, 255, "STRING:\t%.*s", prop->p_vu.p_aval.av_len,
            prop->p_vu.p_aval.av_val);
        break;
    case AMF_DATE:
        snprintf(str, 255, "DATE:\ttimestamp: %.2f, UTC offset: %d",
            prop->p_vu.p_number, prop->p_UTCoffset);
        break;
    default:
        snprintf(str, 255, "INVALID TYPE 0x%02x", (unsigned char)prop->p_type);
    }

    //RTMP_Log(RTMP_LOGDEBUG, "Property: <%s%s>", strRes, str);
}
时间: 2024-10-24 04:41:27

AMFObject 数据格式浅析的相关文章

AMFObject数据格式解析

AMF AMF是Action Message Format的简写,它是一种二进制的数据格式.它的设计是为了把actionscript里面的数据(包括Object, Array, Boolean, Number等)序列化成二进制数据,然后把这段数据随意发送给其他接收方程序,比如发给远程的服务器,在远程服务器那边,可以把这段数据给还原出来,以此达到一个数据传输的作用. 为什么要用AMF 通常情况下我们使用JSON或者XML来做数据的传输,他们的好处是文本数据易读.容易修改,坏处在于文本数据体积较大,

springboot返回统一数据格式及其原理浅析

大家都知道,前后分离之后,后端响应最好以统一的格式的响应. 譬如: 名称 描述   status 状态码,标识请求成功与否,如 [1:成功:-1:失败]   errorCode 错误码,给出明确错误码,更好的应对业务异常:请求成功该值可为空   errorMsg 错误消息,与错误码相对应,更具体的描述异常信息   resultBody 返回结果,通常是 Bean 对象对应的 JSON 数据, 通常为了应对不同返回值类型,将其声明为泛型类型  话不多说,直接上代码 1. 定义一个统一响应结果类Co

浅析WebGIS

浅析WebGIS 摘要:随着网络的发展,利用Web公布信息越来越普及化.而地理信息系统(GIS)与网络的结合就产生了万维网地理信息系统(WebGIS),它引起了地理信息公布的新的变革,对实现GIS信息的共享提供了技术保障.本文阐述了WebGIS的基本概念,说明了WebGIS的体系结构,着重讨论了WebGIS基本的构建方式,叙述了WebGIS的展望.        关键词:GIS  WebGIS  构造方式 1           GIS和WebGIS1.1     地理信息系统(GIS) 地理信

Ajax语法浅析

Ajax是目前很普遍的一门技术,也是很值得探讨和研究的一门技术.本文将针对Ajax的发展过程并结合其在不同库框架中的使用方式来和大家分享下Ajax的那些新老语法. Ajax语法浅析 Ajax简介 Ajax全称为"Asynchronous Javascript And XML",即"异步JavaScript和XML"的意思.通过Ajax我们可以向服务器发送请求,在不阻塞页面的情况下进行数据交互,也可以理解为异步数据传输.在Ajax的帮助下我们的网页只需局部刷新即可更新

netty5 HTTP协议栈浅析与实践

阅读目录 1. 写在前面的话 1.1. 关于netty example 1.2. 关于github项目2. HTTP 协议知多少 2.1. GET请求 2.2. POST请求 2.3. HTTP POST Content-Type3. netty HTTP 编解码 3.1. netty 自带 HTTP 编解码器 3.2. HTTP GET 解析实践 3.3. HTTP POST 解析实践4. 自定义 HTTP POST 的 message body 解码器 4.1. HttpJsonDecode

内存管理 &amp; 内存优化技巧 浅析

内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验.如何让回收那些不再使用的对象呢?本文着重介绍OC中的内存管理. 所谓内存管理,就是对内存进行管理,涉及的操作有: 1.分配内存:比如创建一个对象,会增加内存占用: 2.清除内存:比如销毁一个对象,会减少内存占用. 内存管理的管理范围: 1.任何继承了NSObject的对象: 2.对其他非对象类

Android开发学习笔记:数据存取之SQLite浅析

一.SQLite的介绍 1.SQLite简介 SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入 式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了.它能够支持 Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl.PHP.Java.C++..Net等,还有ODBC接口,同样比起 Mysql.PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的

浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程【转】

本文转载自:http://www.cnblogs.com/qingchen1984/p/7007631.html 本篇文章主要介绍了"浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程",主要涉及到浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程方面的内容,对于浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程感兴趣的同学可以参考一下. 简介: 本文试图完整地描述 Linux 系统中 C 语言编程中的时间问

内存管理 浅析 内存管理/内存优化技巧

内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验.如何让回收那些不再使用的对象呢?本文着重介绍OC中的内存管理. 所谓内存管理,就是对内存进行管理,涉及的操作有: 1.分配内存:比如创建一个对象,会增加内存占用: 2.清除内存:比如销毁一个对象,会减少内存占用. 内存管理的管理范围: 1.任何继承了NSObject的对象: 2.对其他非对象类