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 = , nRes;
if (body[] != 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 ;
} nRes = AMF_Decode(&obj, body, nBodySize, FALSE);
if (nRes < )
{
//RTMP_Log(RTMP_LOGERROR, "%s, error decoding invoke packet", __FUNCTION__);
return ;
}    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[];
char str[];
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.") - ;
}
if (name.av_len > )
name.av_len = ; snprintf(strRes, , "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, , "NUMBER:\t%.2f", prop->p_vu.p_number);
break;
case AMF_BOOLEAN:
snprintf(str, , "BOOLEAN:\t%s",
prop->p_vu.p_number != 0.0 ? "TRUE" : "FALSE");
break;
case AMF_STRING:
snprintf(str, , "STRING:\t%.*s", prop->p_vu.p_aval.av_len,
prop->p_vu.p_aval.av_val);
break;
case AMF_DATE:
snprintf(str, , "DATE:\ttimestamp: %.2f, UTC offset: %d",
prop->p_vu.p_number, prop->p_UTCoffset);
break;
default:
snprintf(str, , "INVALID TYPE 0x%02x", (unsigned char)prop->p_type);
} //RTMP_Log(RTMP_LOGDEBUG, "Property: <%s%s>", strRes, str);
}

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

  1. 【原】AMFObject数据格式详解

    AMF AMF是Action Message Format(动作消息格式)的简写,它是一种二进制的数据格式.它的设计是为了把actionscript里面的数据(包括Object, Array, Boo ...

  2. netty5 HTTP协议栈浅析与实践

      一.说在前面的话 前段时间,工作上需要做一个针对视频质量的统计分析系统,各端(PC端.移动端和 WEB端)将视频质量数据放在一个 HTTP 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...

  3. 浅析WebGIS

    浅析WebGIS 摘要:随着网络的发展,利用Web公布信息越来越普及化.而地理信息系统(GIS)与网络的结合就产生了万维网地理信息系统(WebGIS),它引起了地理信息公布的新的变革,对实现GIS信息 ...

  4. 浅析深究什么是SOA?

    浅析深究什么是SOA? http://blog.vsharing.com/fengjicheng/A1059842.html 金蝶中间件有限公司总经理 奉继承 博士 阅读提示: 本文探讨SOA概念背后 ...

  5. 内存管理 & 内存优化技巧 浅析

    内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户 ...

  6. 用Python浅析股票数据

    用Python浅析股票数据 本文将使用Python来可视化股票数据,比如绘制K线图,并且探究各项指标的含义和关系,最后使用移动平均线方法初探投资策略. 数据导入 这里将股票数据存储在stockData ...

  7. 浅析MVC模式与三层架构的区别

    浅析MVC模式与三层架构的区别 三层架构和MVC是有明显区别的,MVC应该是表现模式(三个加起来以后才是三层架构中的UI层).三层架构(3-tier application) 通常意义上的三层架构就是 ...

  8. 浅析 Bigtable 和 LevelDB 的实现

    在 2006 年的 OSDI 上,Google 发布了名为 Bigtable: A Distributed Storage System for Structured Data 的论文,其中描述了一个 ...

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

    本文转载自:http://www.cnblogs.com/qingchen1984/p/7007631.html 本篇文章主要介绍了"浅析 Linux 中的时间编程和实现原理一—— Linu ...

随机推荐

  1. python面向对象总结

    一 面向对象的程序设计的由来 见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 二 什么是面向对象的程序设计及为什么要有它 面向过 ...

  2. 条款19:定义class就相当于定义一个个的内置类型

    下面的条框应该是谨记的: 1. 新的type应该如何创建与销毁 2. 对象的初始化与赋值应该有什么样的区别 3. 新type的对象如果被pass-by-value,有什么影响? 4. 什么事新type ...

  3. validate参数校验和数据回显

    服务端校验 校验理解 项目中,通常使用较多的是前段的校验,比如在页面中js校验.对于安全要求较高的建议在服务端进行校验. 服务端校验: 控制层controller:校验页面请求的参数的合法性.在服务端 ...

  4. 【python】类file文件处理

    [flush方法] 通常由于缓冲,write不将数据写入文件,而是写入内存的缓冲区,需要使用flush写入文件,并清空缓冲区 文件的flush方法的作用是强制清空缓存写入文件.默认每行flush一下? ...

  5. SBT构建工具

    SBT Simple Build Tool. A interactive build tool. install windows可直接到http://www.scala-sbt.org/0.13/do ...

  6. 人生苦短之我用Python篇(paramiko模块)

    该模块机遇SSH用于连接远程服务器并执行相关操作 基于用户名密码连接: import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在kno ...

  7. [EMWIN]关于 GUI_GetPixelIndex 使用的问题

    在模拟器上和st单片机上使用以下代码: GUI_COLOR color0,color1; color0 = GUI_GetPixelIndex(rect.x1+1, rect.y0);color1 = ...

  8. 21天学通C++_Day3_Part3

    控制程序流程 0.switch...case...语句中省略了break? break让程序能够退出switch结构,如果没有将继续评估后面的case语句 1.如何退出无限循环? 使用break退出当 ...

  9. 深入了解ZooKeeper(二)

    在上篇博客<<深入了解ZooKeeper(一)>>中我们知道了分布式协调技术.分布式锁的实现和zookeeper服务机制,接下来将进一步了解zookeeper究竟能为我们做了什 ...

  10. 模糊聚类算法(FCM)

    伴随着模糊集理论的形成.发展和深化,RusPini率先提出模糊划分的概念.以此为起点和基础,模糊聚类理论和方法迅速蓬勃发展起来.针对不同的应用,人们提出了很多模糊聚类算法,比较典型的有基于相似性关系和 ...